Verifying Merge Sort in Imandra

Merge sort is a widely used efficient general purpose sorting algorithm invented by John von Neumann in 1945. It is a prototypical divide and conquer algorithm and forms the basis of standard library sorting functions in languages like OCaml, Java and Python.

Let's verify it in Imandra!

The main idea

The main idea of merge sort is as follows:

  • Divide the input list into sublists
  • Sort the sublists
  • Merge the sorted sublists to obtain a sorted version of the original list

Merging two lists

We'll start by defining a function to merge two lists in a "sorted" way. Note that our termination proof involves both arguments l and m, using a lexicographic product (via the [@@adm l,m] admission annotation).

In [1]:
let rec merge (l : int list) (m : int list) =
 match l, m with
  | [], _ -> m
  | _, [] -> l
  | a :: ls, b :: ms ->
    if a < b then
     a :: (merge ls m)
    else
     b :: (merge l ms)
[@@adm l, m]
Out[1]:
val merge : int list -> int list -> int list = <fun>
termination proof

Termination proof

call `merge (List.tl l) m` from `merge l m`
originalmerge l m
submerge (List.tl l) m
original ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
sub ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count (List.tl l)); Ordinal.Int (Ordinal.count m)]
path[List.hd l < List.hd m && not (m = []) && not (l = [])]
proof
detailed proof
ground_instances8
definitions2
inductions0
search_time
0.035s
details
Expand
smt_stats
arith offset eqs36
num checks18
arith assert lower151
arith pivots87
rlimit count76133
mk clause230
datatype occurs check269
mk bool var648
arith assert upper156
datatype splits49
decisions374
arith add rows255
arith bound prop5
propagations583
interface eqs6
conflicts41
arith fixed eqs98
datatype accessor ax68
minimized lits5
arith conflicts7
arith assert diseq21
datatype constructor ax78
num allocs1454693777
final checks32
added eqs900
del clause115
arith eq adapter106
memory16.900000
max memory19.730000
Expand
  • start[0.035s]
      List.hd l < List.hd m
      && not (m = [])
         && not (l = [])
            && Ordinal.count l >= 0
               && Ordinal.count m >= 0
                  && Ordinal.count (List.tl l) >= 0 && Ordinal.count m >= 0
      ==> not
          (List.hd (List.tl l) < List.hd m
           && not (m = []) && not (List.tl l = []))
          && not
             (not (List.hd (List.tl l) < List.hd m)
              && not (m = []) && not (List.tl l = []))
          || (if [Ordinal.Int (Ordinal.count (List.tl l));
                  Ordinal.Int (Ordinal.count m)]
                 = []
              then … else …)
             Ordinal.<< …
  • simplify
    into
    (not
     (((((not (List.hd m <= List.hd l) && not (m = [])) && not (l = []))
        && Ordinal.count l >= 0)
       && Ordinal.count m >= 0)
      && Ordinal.count (List.tl l) >= 0)
     || not
        ((not (List.hd m <= List.hd (List.tl l)) && not (m = []))
         && not (List.tl l = []))
        && not
           ((List.hd m <= List.hd (List.tl l) && not (m = []))
            && not (List.tl l = [])))
    || Ordinal.plus
       (Ordinal.shift (Ordinal.Int (Ordinal.count (List.tl l))) (Ordinal.Int 1))
       (Ordinal.Int (Ordinal.count m)) Ordinal.<<
       Ordinal.plus
       (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
       (Ordinal.Int (Ordinal.count m))
    expansions
    []
    rewrite_steps
      forward_chaining
      • unroll
        expr
        (|Ordinal.shift_146|
          (|Ordinal.Int_112| (|count_`int list`_2451| l_2438))
          (|Ordinal.Int_112| 1))
        expansions
        Ordinal.zero
      • unroll
        expr
        (|Ordinal.plus_132|
          (|Ordinal.shift_146|
            (|Ordinal.Int_112| (|count_`int list`_2451| l_2438))
        …
        expansions
        • unroll
          expr
          (|Ordinal.shift_146|
            (|Ordinal.Int_112| (|count_`int list`_2451| (|get.::.1_2437| l_2438)))
            (|Or…
          expansions
          Ordinal.zero
        • unroll
          expr
          (let ((a!1 (|Ordinal.shift_146|
                       (|Ordinal.Int_112|
                         (|count_`int list`_24…
          expansions
          • unroll
            expr
            (let ((a!1 (|Ordinal.shift_146|
                         (|Ordinal.Int_112|
                           (|count_`int list`_24…
            expansions
            • unroll
              expr
              (|count_`int list`_2451| (|get.::.1_2437| l_2438))
              expansions
              • unroll
                expr
                (|count_`int list`_2451| m_2439)
                expansions
                • unroll
                  expr
                  (|count_`int list`_2451| l_2438)
                  expansions
                  • unsat
                    (let ((a!1 (ite (= (|count_`int list`_2451| (|get.::.1_2437| l_2438)) 0)
                                    (|Ordinal.I…

                  call `merge l (List.tl m)` from `merge l m`
                  originalmerge l m
                  submerge l (List.tl m)
                  original ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
                  sub ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count (List.tl m))]
                  path[not (List.hd l < List.hd m) && not (m = []) && not (l = [])]
                  proof
                  detailed proof
                  ground_instances14
                  definitions1
                  inductions0
                  search_time
                  0.062s
                  details
                  Expand
                  smt_stats
                  arith offset eqs38
                  num checks30
                  arith assert lower519
                  arith pivots221
                  rlimit count58124
                  mk clause625
                  datatype occurs check765
                  mk bool var1688
                  arith assert upper523
                  datatype splits160
                  decisions1263
                  arith add rows857
                  arith bound prop26
                  propagations1756
                  interface eqs14
                  conflicts73
                  arith fixed eqs322
                  datatype accessor ax193
                  minimized lits8
                  arith conflicts12
                  arith assert diseq38
                  datatype constructor ax245
                  num allocs1376091714
                  final checks64
                  added eqs2392
                  del clause358
                  arith eq adapter408
                  memory17.090000
                  max memory18.750000
                  Expand
                  • start[0.062s]
                      not (List.hd l < List.hd m)
                      && not (m = [])
                         && not (l = [])
                            && Ordinal.count l >= 0
                               && Ordinal.count m >= 0
                                  && Ordinal.count l >= 0 && Ordinal.count (List.tl m) >= 0
                      ==> not
                          (List.hd l < List.hd (List.tl m)
                           && not (List.tl m = []) && not (l = []))
                          && not
                             (not (List.hd l < List.hd (List.tl m))
                              && not (List.tl m = []) && not (l = []))
                          || (if [Ordinal.Int (Ordinal.count l);
                                  Ordinal.Int (Ordinal.count (List.tl m))]
                                 = []
                              then … else …)
                             Ordinal.<< …
                  • simplify
                    into
                    (not
                     (((((List.hd m <= List.hd l && not (m = [])) && not (l = []))
                        && Ordinal.count l >= 0)
                       && Ordinal.count m >= 0)
                      && Ordinal.count (List.tl m) >= 0)
                     || not
                        ((not (List.hd (List.tl m) <= List.hd l) && not (List.tl m = []))
                         && not (l = []))
                        && not
                           ((List.hd (List.tl m) <= List.hd l && not (List.tl m = []))
                            && not (l = [])))
                    || Ordinal.plus
                       (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
                       (Ordinal.Int (Ordinal.count (List.tl m))) Ordinal.<<
                       Ordinal.plus
                       (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
                       (Ordinal.Int (Ordinal.count m))
                    expansions
                    []
                    rewrite_steps
                      forward_chaining
                      • unroll
                        expr
                        (|Ordinal.plus_132|
                          (|Ordinal.shift_146|
                            (|Ordinal.Int_112| (|count_`int list`_2451| l_2438))
                        …
                        expansions
                        • unroll
                          expr
                          (|Ordinal.shift_146|
                            (|Ordinal.Int_112| (|count_`int list`_2451| l_2438))
                            (|Ordinal.Int_112| 1))
                          expansions
                          Ordinal.zero
                        • unroll
                          expr
                          (|Ordinal.plus_132|
                            (|Ordinal.shift_146|
                              (|Ordinal.Int_112| (|count_`int list`_2451| l_2438))
                          …
                          expansions
                          • unroll
                            expr
                            (let ((a!1 (|Ordinal.plus_132|
                                         (|Ordinal.shift_146|
                                           (|Ordinal.Int_112| (…
                            expansions
                            • unroll
                              expr
                              (|count_`int list`_2451| (|get.::.1_2437| m_2439))
                              expansions
                              • unroll
                                expr
                                (|count_`int list`_2451| m_2439)
                                expansions
                                • unroll
                                  expr
                                  (|count_`int list`_2451| l_2438)
                                  expansions
                                  • unroll
                                    expr
                                    (|count_`int list`_2451| (|get.::.1_2437| l_2438))
                                    expansions
                                    • unroll
                                      expr
                                      (|count_`int list`_2451| (|get.::.1_2437| (|get.::.1_2437| m_2439)))
                                      expansions
                                      • unroll
                                        expr
                                        (let ((a!1 (|get.Ordinal.Cons.2_2444|
                                                     (|Ordinal.shift_146|
                                                       (|Ordinal.Int…
                                        expansions
                                        • unroll
                                          expr
                                          (let ((a!1 (|get.Ordinal.Cons.0_2442|
                                                       (|Ordinal.shift_146|
                                                         (|Ordinal.Int…
                                          expansions
                                          • unroll
                                            expr
                                            (let ((a!1 (|get.Ordinal.Cons.2_2444|
                                                         (|Ordinal.shift_146|
                                                           (|Ordinal.Int…
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|Ordinal.plus_132|
                                                           (|Ordinal.shift_146|
                                                             (|Ordinal.Int_112| (…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|Ordinal.plus_132|
                                                             (|Ordinal.shift_146|
                                                               (|Ordinal.Int_112| (…
                                                expansions
                                                • unsat
                                                  (let ((a!1 (|get.Ordinal.Int.0_2441|
                                                               (|Ordinal.shift_146|
                                                                 (|Ordinal.Int_…

                                                Let's experiment a bit with merge.

                                                In [2]:
                                                merge [1;2;3] [4;5;6]
                                                
                                                Out[2]:
                                                - : int list = [1; 2; 3; 4; 5; 6]
                                                
                                                In [3]:
                                                merge [1;4;5] [2;3;4]
                                                
                                                Out[3]:
                                                - : int list = [1; 2; 3; 4; 4; 5]
                                                
                                                In [4]:
                                                merge [1;5;2] [2;3]
                                                
                                                Out[4]:
                                                - : int list = [1; 2; 3; 5; 2]
                                                

                                                Observe that merge will merge sorted lists in a manner that respects their sortedness. But, if the lists given to merge aren't sorted, the output of merge need not be sorted.

                                                Dividing into sublists

                                                In merge sort, we need to divide a list into sublists. We'll do this in a simple way using the function odds which computes "every other" element of a list. We'll then be able to split a list x into sublists by taking odds x and odds (List.tl x).

                                                In [5]:
                                                let rec odds l =
                                                 match l with
                                                  | []  -> []
                                                  | [x] -> [x]
                                                  | x :: y :: rst -> x :: odds rst
                                                
                                                Out[5]:
                                                val odds : 'a list -> 'a list = <fun>
                                                
                                                termination proof

                                                Termination proof

                                                call `odds (List.tl (List.tl l))` from `odds l`
                                                originalodds l
                                                subodds (List.tl (List.tl l))
                                                original ordinalOrdinal.Int (Ordinal.count l)
                                                sub ordinalOrdinal.Int (Ordinal.count (List.tl (List.tl l)))
                                                path[not (List.tl l = [] && l <> []) && not (l = [])]
                                                proof
                                                detailed proof
                                                ground_instances6
                                                definitions0
                                                inductions0
                                                search_time
                                                0.021s
                                                details
                                                Expand
                                                smt_stats
                                                arith offset eqs4
                                                num checks14
                                                arith assert lower28
                                                arith pivots16
                                                rlimit count81313
                                                mk clause72
                                                datatype occurs check36
                                                mk bool var160
                                                arith assert upper25
                                                datatype splits3
                                                decisions44
                                                arith add rows37
                                                arith bound prop5
                                                propagations44
                                                interface eqs1
                                                conflicts18
                                                arith fixed eqs23
                                                datatype accessor ax9
                                                minimized lits1
                                                arith conflicts3
                                                arith assert diseq3
                                                datatype constructor ax19
                                                num allocs1516568359
                                                final checks9
                                                added eqs105
                                                del clause20
                                                arith eq adapter20
                                                memory21.330000
                                                max memory21.330000
                                                Expand
                                                • start[0.021s]
                                                    not (List.tl l = [] && l <> [])
                                                    && not (l = [])
                                                       && Ordinal.count l >= 0 && Ordinal.count (List.tl (List.tl l)) >= 0
                                                    ==> not
                                                        (not
                                                         (List.tl (List.tl (List.tl l)) = [] && (List.tl (List.tl l)) <> [])
                                                         && not (List.tl (List.tl l) = []))
                                                        || Ordinal.Int (Ordinal.count (List.tl (List.tl l))) Ordinal.<<
                                                           Ordinal.Int (Ordinal.count l)
                                                • simplify
                                                  into
                                                  (not
                                                   (((not (List.tl l = [] && l <> []) && not (l = [])) && Ordinal.count l >= 0)
                                                    && Ordinal.count (List.tl (List.tl l)) >= 0)
                                                   || not
                                                      (not (List.tl (List.tl (List.tl l)) = [] && (List.tl (List.tl l)) <> [])
                                                       && not (List.tl (List.tl l) = [])))
                                                  || Ordinal.Int (Ordinal.count (List.tl (List.tl l))) Ordinal.<<
                                                     Ordinal.Int (Ordinal.count l)
                                                  expansions
                                                  []
                                                  rewrite_steps
                                                    forward_chaining
                                                    • unroll
                                                      expr
                                                      (let ((a!1 (|Ordinal.Int_112|
                                                                   (|count_`ty_0 list`_2492|
                                                                     (|get.::.1_2480|…
                                                      expansions
                                                      • unroll
                                                        expr
                                                        (|count_`ty_0 list`_2492| (|get.::.1_2480| (|get.::.1_2480| l_2487)))
                                                        expansions
                                                        • unroll
                                                          expr
                                                          (|count_`ty_0 list`_2492| l_2487)
                                                          expansions
                                                          • unroll
                                                            expr
                                                            (|count_`ty_0 list`_2492|
                                                              (|get.::.1_2480| (|get.::.1_2480| (|get.::.1_2480| l_2487))))
                                                            expansions
                                                            • unroll
                                                              expr
                                                              (let ((a!1 (|Ordinal.Int_112|
                                                                           (|count_`ty_0 list`_2492|
                                                                             (|get.::.1_2480|…
                                                              expansions
                                                              • unroll
                                                                expr
                                                                (|count_`ty_0 list`_2492| (|get.::.1_2480| l_2487))
                                                                expansions
                                                                • unsat
                                                                  (let ((a!1 (ite (>= (|count_`ty_0 list`_2492| (|get.::.1_2480| l_2487)) 0)
                                                                                  (|count_`…

                                                                Let's compute a bit with odds to better understand how it works.

                                                                In [6]:
                                                                odds [1;2;3;4;5;6]
                                                                
                                                                Out[6]:
                                                                - : Z.t list = [1; 3; 5]
                                                                
                                                                In [7]:
                                                                odds (List.tl [1;2;3;4;5;6])
                                                                
                                                                Out[7]:
                                                                - : Z.t list = [2; 4; 6]
                                                                

                                                                Defining Merge Sort

                                                                We can now put the pieces together and define our main merge_sort function, as follows:

                                                                In [8]:
                                                                let rec merge_sort l =
                                                                 match l with
                                                                  | []  -> []
                                                                  | [_] -> l
                                                                  | _ :: ls -> merge (merge_sort (odds l)) (merge_sort (odds ls))
                                                                
                                                                Out[8]:
                                                                val merge_sort : int list -> int list = <fun>
                                                                File "jupyter cell 8", line 1, characters 0-129:
                                                                Error: rejected definition for function merge_sort,
                                                                Imandra could not prove termination. 
                                                                hint: problematic sub-call from `merge_sort l`
                                                                to `merge_sort (odds (List.tl l))`  under path
                                                                not (List.tl l = [] && l <> []) and not (l = [])
                                                                could not be proved to decrease (measured subset: (l))
                                                                

                                                                To admit merge_sort into Imandra, we must prove it terminating. We can do this with a custom measure function which we'll call merge_sort_measure. We'll prove a lemma about odds (by functional induction) to make it clear why the measure is decreasing in every recursive call. We'll install the lemma as a forward_chaining rule, which is a good strategy for making it effective during termination analysis.

                                                                In [9]:
                                                                let merge_sort_measure x =
                                                                 Ordinal.of_int (List.length x)
                                                                
                                                                Out[9]:
                                                                val merge_sort_measure : 'a list -> Ordinal.t = <fun>
                                                                
                                                                In [10]:
                                                                theorem odds_len_1 x =
                                                                 x <> [] && List.tl x <> []
                                                                 ==>
                                                                 (List.length (odds x) [@trigger]) < List.length x
                                                                [@@induct functional odds] [@@forward_chaining]
                                                                
                                                                Out[10]:
                                                                val odds_len_1 : 'a list -> bool = <fun>
                                                                Goal:
                                                                
                                                                x <> [] && List.tl x <> [] ==> List.length (odds x) < List.length x.
                                                                
                                                                1 nontautological subgoal.
                                                                
                                                                Subgoal 1:
                                                                
                                                                 H0. not (x = [])
                                                                 H1. not (List.tl x = [])
                                                                 H2. List.length x <= List.length (odds x)
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                This simplifies, using the definition of List.length to:
                                                                
                                                                Subgoal 1':
                                                                
                                                                 H0. List.length (List.tl x) <= (-1 + List.length (odds x))
                                                                 H1. (List.tl x) <> []
                                                                 H2. x <> []
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                Verified up to bound 10 (after 0.021s).
                                                                
                                                                We can eliminate destructors by the following substitution:
                                                                 x -> x1 :: x2
                                                                
                                                                This produces the modified subgoal:
                                                                
                                                                Subgoal 1'':
                                                                
                                                                 H0. List.length x2 <= (-1 + List.length (odds (x1 :: x2)))
                                                                 H1. x2 <> []
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                This simplifies, using the definitions of List.length and odds to:
                                                                
                                                                Subgoal 1''':
                                                                
                                                                 H0. x2 <> []
                                                                 H1. List.length x2 <= List.length (odds (List.tl x2))
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                This simplifies, using the definition of List.length to:
                                                                
                                                                Subgoal 1'''':
                                                                
                                                                 H0. List.length (List.tl x2) <= (-1 + List.length (odds (List.tl x2)))
                                                                 H1. x2 <> []
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                Verified up to bound 10 (after 0.020s).
                                                                
                                                                Must try induction.
                                                                
                                                                Note: We must proceed by induction, but our current subgoal is less
                                                                appropriate for induction than our original conjecture. Thus, we prefer to
                                                                abandon our work until now and return our focus to the original conjecture
                                                                which we shall attempt to prove by induction directly.
                                                                
                                                                We shall induct according to a scheme derived from odds.
                                                                
                                                                Induction scheme:
                                                                
                                                                 (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                 && (not (x = [])
                                                                     && not (List.tl x = [] && x <> []) && φ (List.tl (List.tl x)) ==> 
                                                                     φ x).
                                                                
                                                                2 nontautological subgoals.
                                                                
                                                                Subgoal 2:
                                                                
                                                                 H0. not (x = [])
                                                                 H1. not (List.tl x = [])
                                                                 H2. List.length x <= List.length (odds x)
                                                                |---------------------------------------------------------------------------
                                                                 not (List.tl x = [] && x <> []) && not (x = [])
                                                                
                                                                But simplification reduces this to true, using the forward-chaining rule
                                                                List.len_nonnegative.
                                                                
                                                                Subgoal 1:
                                                                
                                                                 H0. not (x = [])
                                                                 H1. not (List.tl x = [] && x <> [])
                                                                 H2. not
                                                                     (not (List.tl (List.tl x) = [])
                                                                      && not (List.tl (List.tl (List.tl x)) = []))
                                                                     || not
                                                                        (List.length (List.tl (List.tl x)) <=
                                                                         List.length (odds (List.tl (List.tl x))))
                                                                 H3. not (x = [])
                                                                 H4. not (List.tl x = [])
                                                                 H5. List.length x <= List.length (odds x)
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                This simplifies, using the definitions of List.length and odds to the
                                                                following 3 subgoals:
                                                                
                                                                Subgoal 1.3:
                                                                
                                                                 H0. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                 H1. (List.tl x) <> []
                                                                 H2. List.tl (List.tl x) = []
                                                                 H3. x <> []
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                But simplification reduces this to true, using the definitions of List.length
                                                                and odds.
                                                                
                                                                Subgoal 1.2:
                                                                
                                                                 H0. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                 H1. (List.tl x) <> []
                                                                 H2. (List.tl (List.tl x)) <> []
                                                                 H3. (List.tl (List.tl (List.tl x))) <> []
                                                                 H4. x <> []
                                                                |---------------------------------------------------------------------------
                                                                 List.length (List.tl (List.tl x)) <=
                                                                 List.length (odds (List.tl (List.tl x)))
                                                                
                                                                But simplification reduces this to true, using the definition of List.length.
                                                                
                                                                Subgoal 1.1:
                                                                
                                                                 H0. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                 H1. (List.tl x) <> []
                                                                 H2. (List.tl (List.tl x)) <> []
                                                                 H3. List.tl (List.tl (List.tl x)) = []
                                                                 H4. x <> []
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                This simplifies, using the definitions of List.length and odds to:
                                                                
                                                                Subgoal 1.1':
                                                                
                                                                 H0. x <> []
                                                                 H1. List.tl (List.tl (List.tl x)) = []
                                                                 H2. (List.tl (List.tl x)) <> []
                                                                 H3. (List.tl x) <> []
                                                                 H4. List.length (List.tl (List.tl x)) <=
                                                                     List.length (List.tl (List.tl (List.tl x)))
                                                                |---------------------------------------------------------------------------
                                                                 false
                                                                
                                                                But simplification reduces this to true, using the definition of List.length.
                                                                
                                                                
                                                                Proved
                                                                proof
                                                                ground_instances0
                                                                definitions21
                                                                inductions1
                                                                search_time
                                                                0.326s
                                                                Expand
                                                                • start[0.326s, "Goal"]
                                                                    not (:var_0: = []) && not (List.tl :var_0: = [])
                                                                    ==> List.length (odds :var_0:) < List.length :var_0:
                                                                • subproof

                                                                  (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                  • start[0.326s, "1"]
                                                                      (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                  • simplify
                                                                    into
                                                                    (not (List.length (List.tl x) <= (-1 + List.length (odds x)))
                                                                     || List.tl x = [])
                                                                    || x = []
                                                                    expansions
                                                                    List.length
                                                                    rewrite_steps
                                                                      forward_chaining
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                      • List.len_nonnegative
                                                                    • Elim_destructor (:cstor :: :replace x1 :: x2 :context [])
                                                                    • simplify
                                                                      into
                                                                      not (x2 <> []) || not (List.length x2 <= List.length (odds (List.tl x2)))
                                                                      expansions
                                                                      [List.length, odds]
                                                                      rewrite_steps
                                                                        forward_chaining
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                      • simplify
                                                                        into
                                                                        not (List.length (List.tl x2) <= (-1 + List.length (odds (List.tl x2))))
                                                                        || not (x2 <> [])
                                                                        expansions
                                                                        List.length
                                                                        rewrite_steps
                                                                          forward_chaining
                                                                          • List.len_nonnegative
                                                                          • List.len_nonnegative
                                                                          • List.len_nonnegative
                                                                          • List.len_nonnegative
                                                                          • List.len_nonnegative
                                                                        • induction on (functional odds)
                                                                          :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                  && (not (x = [])
                                                                                      && not (List.tl x = [] && x <> []) && φ (List.tl (List.tl x))
                                                                                      ==> φ x)
                                                                        • Split (((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                   || not (not (x = []) && not (List.tl x = [])))
                                                                                  || not (List.length x <= List.length (odds x)))
                                                                                 && ((not
                                                                                      ((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                       && (not
                                                                                           (not (List.tl (List.tl x) = [])
                                                                                            && not (List.tl (List.tl (List.tl x)) = []))
                                                                                           || not
                                                                                              (List.length (List.tl (List.tl x)) <=
                                                                                               List.length (odds (List.tl (List.tl x))))))
                                                                                      || not (not (x = []) && not (List.tl x = [])))
                                                                                     || not (List.length x <= List.length (odds x)))
                                                                                 :cases [((x = [] || List.tl x = [])
                                                                                          || not (List.length x <= List.length (odds x)))
                                                                                         || not (List.tl x = [] && x <> []) && not (x = []);
                                                                                         (((x = [] || List.tl x = [] && x <> [])
                                                                                           || not
                                                                                              (not
                                                                                               (not (List.tl (List.tl x) = [])
                                                                                                && not (List.tl (List.tl (List.tl x)) = []))
                                                                                               || not
                                                                                                  (List.length (List.tl (List.tl x)) <=
                                                                                                   List.length (odds (List.tl (List.tl x))))))
                                                                                          || List.tl x = [])
                                                                                         || not (List.length x <= List.length (odds x))])
                                                                          • subproof
                                                                            (((x = [] || List.tl x = [] && x <> []) || not (not (not (List.tl (List.tl x) = []) && not (List.tl (List.tl (List.tl x)) = [])) || not (List.length (List.tl (List.tl x)) <= List.length (odds (List.tl (List.tl x)))))) || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                            • start[0.172s, "1"]
                                                                                (((x = [] || List.tl x = [] && x <> [])
                                                                                  || not
                                                                                     (not
                                                                                      (not (List.tl (List.tl x) = [])
                                                                                       && not (List.tl (List.tl (List.tl x)) = []))
                                                                                      || not
                                                                                         (List.length (List.tl (List.tl x)) <=
                                                                                          List.length (odds (List.tl (List.tl x))))))
                                                                                 || List.tl x = [])
                                                                                || not (List.length x <= List.length (odds x))
                                                                            • simplify
                                                                              into
                                                                              ((((not (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x))))
                                                                                  || List.tl x = [])
                                                                                 || not (List.tl (List.tl x) = []))
                                                                                || x = [])
                                                                               && (((((not
                                                                                       (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x))))
                                                                                       || List.tl x = [])
                                                                                      || List.length (List.tl (List.tl x)) <=
                                                                                         List.length (odds (List.tl (List.tl x))))
                                                                                     || List.tl (List.tl x) = [])
                                                                                    || List.tl (List.tl (List.tl x)) = [])
                                                                                   || x = []))
                                                                              && ((((not
                                                                                     (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x))))
                                                                                     || List.tl x = [])
                                                                                    || List.tl (List.tl x) = [])
                                                                                   || not (List.tl (List.tl (List.tl x)) = []))
                                                                                  || x = [])
                                                                              expansions
                                                                              [List.length, odds, List.length, List.length, odds, List.length, List.length,
                                                                               odds, List.length]
                                                                              rewrite_steps
                                                                                forward_chaining
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • Subproof
                                                                                • Subproof
                                                                                • Subproof
                                                                            • subproof
                                                                              ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))) || not (List.tl x = [] && x <> []) && not (x = [])
                                                                              • start[0.172s, "2"]
                                                                                  ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x)))
                                                                                  || not (List.tl x = [] && x <> []) && not (x = [])
                                                                              • simplify
                                                                                into
                                                                                true
                                                                                expansions
                                                                                []
                                                                                rewrite_steps
                                                                                  forward_chaining
                                                                                  • List.len_nonnegative
                                                                                  • List.len_nonnegative

                                                                          Now we're ready to define merge_sort. Imandra is able prove it terminating using our custom measure (and lemma!).

                                                                          In [11]:
                                                                          let rec merge_sort l =
                                                                           match l with
                                                                            | []  -> []
                                                                            | [_] -> l
                                                                            | _ :: ls -> merge (merge_sort (odds l)) (merge_sort (odds ls))
                                                                          [@@measure merge_sort_measure l]
                                                                          
                                                                          Out[11]:
                                                                          val merge_sort : int list -> int list = <fun>
                                                                          
                                                                          termination proof

                                                                          Termination proof

                                                                          call `merge_sort (odds l)` from `merge_sort l`
                                                                          originalmerge_sort l
                                                                          submerge_sort (odds l)
                                                                          original ordinalmerge_sort_measure l
                                                                          sub ordinalmerge_sort_measure (odds l)
                                                                          path[not (List.tl l = [] && l <> []) && not (l = [])]
                                                                          proof
                                                                          detailed proof
                                                                          ground_instances1
                                                                          definitions0
                                                                          inductions0
                                                                          search_time
                                                                          0.012s
                                                                          details
                                                                          Expand
                                                                          smt_stats
                                                                          num checks3
                                                                          arith assert lower2
                                                                          arith pivots1
                                                                          rlimit count106377
                                                                          mk clause3
                                                                          datatype occurs check15
                                                                          mk bool var46
                                                                          arith assert upper4
                                                                          datatype splits4
                                                                          decisions11
                                                                          propagations4
                                                                          conflicts8
                                                                          datatype accessor ax7
                                                                          datatype constructor ax12
                                                                          final checks3
                                                                          added eqs39
                                                                          del clause3
                                                                          memory41.770000
                                                                          max memory41.770000
                                                                          num allocs6597159037.000000
                                                                          Expand
                                                                          • start[0.012s]
                                                                              not (List.tl l = [] && l <> [])
                                                                              && not (l = [])
                                                                                 && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                    && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >=
                                                                                       0
                                                                              ==> not
                                                                                  (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = []))
                                                                                  && not
                                                                                     (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = []))
                                                                                  || Ordinal.Int
                                                                                     (if List.length (odds l) >= 0 then List.length (odds l) else 0)
                                                                                     Ordinal.<<
                                                                                     Ordinal.Int (if List.length l >= 0 then List.length l else 0)
                                                                          • simplify
                                                                            into
                                                                            (not
                                                                             (((not (List.tl l = [] && l <> []) && not (l = []))
                                                                               && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                              && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >= 0)
                                                                             || not (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = [])))
                                                                            || Ordinal.Int
                                                                               (if List.length (odds l) >= 0 then List.length (odds l) else 0) Ordinal.<<
                                                                               Ordinal.Int (if List.length l >= 0 then List.length l else 0)
                                                                            expansions
                                                                            []
                                                                            rewrite_steps
                                                                              forward_chaining
                                                                              • unroll
                                                                                expr
                                                                                (let ((a!1 (ite (>= (|List.length_2619| (odds_2623 l_2629)) 0)
                                                                                                (|List.length_2619| (…
                                                                                expansions
                                                                                • unsat
                                                                                  (let ((a!1 (and (not (= l_2629 |[]_2|))
                                                                                                  (not (= (|get.::.1_2612| l_2629) |[]_2|))))
                                                                                  …

                                                                                call `merge_sort (odds (List.tl l))` from `merge_sort l`
                                                                                originalmerge_sort l
                                                                                submerge_sort (odds (List.tl l))
                                                                                original ordinalmerge_sort_measure l
                                                                                sub ordinalmerge_sort_measure (odds (List.tl l))
                                                                                path[not (List.tl l = [] && l <> []) && not (l = [])]
                                                                                proof
                                                                                detailed proof
                                                                                ground_instances4
                                                                                definitions0
                                                                                inductions0
                                                                                search_time
                                                                                0.018s
                                                                                details
                                                                                Expand
                                                                                smt_stats
                                                                                num checks10
                                                                                arith assert lower17
                                                                                arith pivots6
                                                                                rlimit count104761
                                                                                mk clause15
                                                                                datatype occurs check67
                                                                                mk bool var117
                                                                                arith assert upper3
                                                                                datatype splits18
                                                                                decisions31
                                                                                arith add rows8
                                                                                propagations31
                                                                                conflicts14
                                                                                datatype accessor ax14
                                                                                arith conflicts1
                                                                                datatype constructor ax25
                                                                                final checks15
                                                                                added eqs102
                                                                                del clause8
                                                                                arith eq adapter2
                                                                                memory38.940000
                                                                                max memory41.200000
                                                                                num allocs6482561914.000000
                                                                                Expand
                                                                                • start[0.018s]
                                                                                    not (List.tl l = [] && l <> [])
                                                                                    && not (l = [])
                                                                                       && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                          && (if List.length (odds (List.tl l)) >= 0
                                                                                              then List.length (odds (List.tl l)) else 0)
                                                                                             >= 0
                                                                                    ==> not
                                                                                        (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                         && not (odds (List.tl l) = []))
                                                                                        && not
                                                                                           (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                            && not (odds (List.tl l) = []))
                                                                                        || Ordinal.Int
                                                                                           (if List.length (odds (List.tl l)) >= 0
                                                                                            then List.length (odds (List.tl l)) else 0)
                                                                                           Ordinal.<<
                                                                                           Ordinal.Int (if List.length l >= 0 then List.length l else 0)
                                                                                • simplify
                                                                                  into
                                                                                  (not
                                                                                   (((not (List.tl l = [] && l <> []) && not (l = []))
                                                                                     && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                                    && (if List.length (odds (List.tl l)) >= 0
                                                                                        then List.length (odds (List.tl l)) else 0)
                                                                                       >= 0)
                                                                                   || not
                                                                                      (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                       && not (odds (List.tl l) = [])))
                                                                                  || Ordinal.Int
                                                                                     (if List.length (odds (List.tl l)) >= 0
                                                                                      then List.length (odds (List.tl l)) else 0)
                                                                                     Ordinal.<< Ordinal.Int (if List.length l >= 0 then List.length l else 0)
                                                                                  expansions
                                                                                  []
                                                                                  rewrite_steps
                                                                                    forward_chaining
                                                                                    • unroll
                                                                                      expr
                                                                                      (let ((a!1 (>= (|List.length_2619| (odds_2623 (|get.::.1_2612| l_2629))) 0))
                                                                                            (a!3 (|Ordinal.In…
                                                                                      expansions
                                                                                      • unroll
                                                                                        expr
                                                                                        (odds_2623 (|get.::.1_2612| l_2629))
                                                                                        expansions
                                                                                        • unroll
                                                                                          expr
                                                                                          (|List.length_2619| (odds_2623 (|get.::.1_2612| l_2629)))
                                                                                          expansions
                                                                                          • unroll
                                                                                            expr
                                                                                            (|List.length_2619| l_2629)
                                                                                            expansions
                                                                                            • unsat
                                                                                              (let ((a!1 (= (|get.::.1_2612| (odds_2623 (|get.::.1_2612| l_2629))) |[]_2|))
                                                                                                    (a!3 (not ((_ is…

                                                                                            Let's experiment a bit with merge_sort to gain confidence we've defined it correctly.

                                                                                            In [12]:
                                                                                            merge_sort [1;2;3]
                                                                                            
                                                                                            Out[12]:
                                                                                            - : int list = [1; 2; 3]
                                                                                            
                                                                                            In [13]:
                                                                                            merge_sort [9;100;6;2;34;19;3;4;7;6]
                                                                                            
                                                                                            Out[13]:
                                                                                            - : int list = [2; 3; 4; 6; 6; 7; 9; 19; 34; 100]
                                                                                            

                                                                                            This looks pretty good! Let's now use Imandra to prove it correct.

                                                                                            Proving Merge Sort correct

                                                                                            What does it mean for a sorting algorithm to be correct? There are two main components:

                                                                                            • The result is sorted
                                                                                            • The result has the same elements as the original

                                                                                            Let's start by defining what it means for a list to be sorted.

                                                                                            In [14]:
                                                                                            let rec is_sorted (x : int list) =
                                                                                             match x with
                                                                                              | []  -> true
                                                                                              | [_] -> true
                                                                                              | x :: x' :: xs -> x <= x' && is_sorted (x' :: xs)
                                                                                            
                                                                                            Out[14]:
                                                                                            val is_sorted : int list -> bool = <fun>
                                                                                            
                                                                                            termination proof

                                                                                            Termination proof

                                                                                            call `is_sorted (List.tl x)` from `is_sorted x`
                                                                                            originalis_sorted x
                                                                                            subis_sorted (List.tl x)
                                                                                            original ordinalOrdinal.Int (Ordinal.count x)
                                                                                            sub ordinalOrdinal.Int (Ordinal.count (List.tl x))
                                                                                            path[List.hd x <= List.hd (List.tl x) && not (List.tl x = [] && x <> []) && not (x = [])]
                                                                                            proof
                                                                                            detailed proof
                                                                                            ground_instances3
                                                                                            definitions0
                                                                                            inductions0
                                                                                            search_time
                                                                                            0.014s
                                                                                            details
                                                                                            Expand
                                                                                            smt_stats
                                                                                            num checks8
                                                                                            arith assert lower19
                                                                                            arith pivots11
                                                                                            rlimit count109286
                                                                                            mk clause20
                                                                                            datatype occurs check23
                                                                                            mk bool var93
                                                                                            arith assert upper12
                                                                                            datatype splits3
                                                                                            decisions16
                                                                                            arith add rows20
                                                                                            arith bound prop1
                                                                                            propagations14
                                                                                            conflicts12
                                                                                            arith fixed eqs7
                                                                                            datatype accessor ax6
                                                                                            arith conflicts2
                                                                                            datatype constructor ax12
                                                                                            final checks5
                                                                                            added eqs61
                                                                                            del clause8
                                                                                            arith eq adapter10
                                                                                            memory42.240000
                                                                                            max memory42.240000
                                                                                            num allocs6809535601.000000
                                                                                            Expand
                                                                                            • start[0.014s]
                                                                                                List.hd x <= List.hd (List.tl x)
                                                                                                && not (List.tl x = [] && x <> [])
                                                                                                   && not (x = [])
                                                                                                      && Ordinal.count x >= 0 && Ordinal.count (List.tl x) >= 0
                                                                                                ==> not
                                                                                                    (List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                     && not (List.tl (List.tl x) = [] && (List.tl x) <> [])
                                                                                                        && not (List.tl x = []))
                                                                                                    || Ordinal.Int (Ordinal.count (List.tl x)) Ordinal.<<
                                                                                                       Ordinal.Int (Ordinal.count x)
                                                                                            • simplify
                                                                                              into
                                                                                              (not
                                                                                               ((((List.hd x <= List.hd (List.tl x) && not (List.tl x = [] && x <> []))
                                                                                                  && not (x = []))
                                                                                                 && Ordinal.count x >= 0)
                                                                                                && Ordinal.count (List.tl x) >= 0)
                                                                                               || not
                                                                                                  ((List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                    && not (List.tl (List.tl x) = [] && (List.tl x) <> []))
                                                                                                   && not (List.tl x = [])))
                                                                                              || Ordinal.Int (Ordinal.count (List.tl x)) Ordinal.<<
                                                                                                 Ordinal.Int (Ordinal.count x)
                                                                                              expansions
                                                                                              []
                                                                                              rewrite_steps
                                                                                                forward_chaining
                                                                                                • unroll
                                                                                                  expr
                                                                                                  (|Ordinal.<<_121| (|Ordinal.Int_112|
                                                                                                                      (|count_`int list`_2652| (|get.::.1_2612| x…
                                                                                                  expansions
                                                                                                  • unroll
                                                                                                    expr
                                                                                                    (|count_`int list`_2652| (|get.::.1_2612| x_2647))
                                                                                                    expansions
                                                                                                    • unroll
                                                                                                      expr
                                                                                                      (|count_`int list`_2652| x_2647)
                                                                                                      expansions
                                                                                                      • unsat
                                                                                                        (let ((a!1 (>= (ite (>= (|get.::.0_2611| x_2647) 0) (|get.::.0_2611| x_2647) 0)
                                                                                                                       0))
                                                                                                         …

                                                                                                      As usual, let's experiment a bit with this definition.

                                                                                                      In [15]:
                                                                                                      is_sorted [1;2;3;4;5]
                                                                                                      
                                                                                                      Out[15]:
                                                                                                      - : bool = true
                                                                                                      
                                                                                                      In [16]:
                                                                                                      is_sorted [1;4;2]
                                                                                                      
                                                                                                      Out[16]:
                                                                                                      - : bool = false
                                                                                                      
                                                                                                      In [17]:
                                                                                                      is_sorted [1]
                                                                                                      
                                                                                                      Out[17]:
                                                                                                      - : bool = true
                                                                                                      
                                                                                                      In [18]:
                                                                                                      instance (fun x -> List.length x >= 5 && is_sorted x)
                                                                                                      
                                                                                                      Out[18]:
                                                                                                      - : int list -> bool = <fun>
                                                                                                      module CX : sig val x : Z.t list end
                                                                                                      
                                                                                                      Instance (after 11 steps, 0.024s):
                                                                                                       let x = [7719; 7719; 16574; 18856; 24709]
                                                                                                      
                                                                                                      Instance
                                                                                                      proof attempt
                                                                                                      ground_instances11
                                                                                                      definitions0
                                                                                                      inductions0
                                                                                                      search_time
                                                                                                      0.024s
                                                                                                      details
                                                                                                      Expand
                                                                                                      smt_stats
                                                                                                      num checks23
                                                                                                      arith assert lower60
                                                                                                      arith pivots27
                                                                                                      rlimit count8759
                                                                                                      mk clause104
                                                                                                      datatype occurs check73
                                                                                                      mk bool var319
                                                                                                      arith assert upper38
                                                                                                      datatype splits38
                                                                                                      decisions96
                                                                                                      arith add rows128
                                                                                                      propagations201
                                                                                                      interface eqs1
                                                                                                      conflicts36
                                                                                                      arith fixed eqs35
                                                                                                      datatype accessor ax24
                                                                                                      arith conflicts11
                                                                                                      arith assert diseq10
                                                                                                      datatype constructor ax42
                                                                                                      final checks37
                                                                                                      added eqs307
                                                                                                      del clause72
                                                                                                      arith eq adapter38
                                                                                                      memory42.760000
                                                                                                      max memory42.760000
                                                                                                      num allocs7027451161.000000
                                                                                                      Expand
                                                                                                      • start[0.024s] List.length :var_0: >= 5 && is_sorted :var_0:
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (is_sorted_2641 x_2655)
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|List.length_2661| x_2655)
                                                                                                          expansions
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (|List.length_2661| (|get.::.1_2660| x_2655))
                                                                                                            expansions
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (|List.length_2661| (|get.::.1_2660| (|get.::.1_2660| x_2655)))
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (is_sorted_2641 (|get.::.1_2660| x_2655))
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (|List.length_2661|
                                                                                                                    (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| x_2655))))
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (is_sorted_2641 (|get.::.1_2660| (|get.::.1_2660| x_2655)))
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (let ((a!1 (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| x_2655))))))
                                                                                                                        (|List…
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (is_sorted_2641 (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| x_2655))))
                                                                                                                        expansions
                                                                                                                        • unroll
                                                                                                                          expr
                                                                                                                          (let ((a!1 (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| x_2655))))))
                                                                                                                            (|List…
                                                                                                                          expansions
                                                                                                                          • unroll
                                                                                                                            expr
                                                                                                                            (let ((a!1 (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| (|get.::.1_2660| x_2655))))))
                                                                                                                              (is_so…
                                                                                                                            expansions
                                                                                                                            • Sat (Some let x = [7719; 7719; 16574; 18856; 24709] )
                                                                                                                            In [19]:
                                                                                                                            instance (fun x -> List.length x >= 5 && is_sorted x && is_sorted (List.rev x))
                                                                                                                            
                                                                                                                            Out[19]:
                                                                                                                            - : int list -> bool = <fun>
                                                                                                                            module CX : sig val x : Z.t list end
                                                                                                                            
                                                                                                                            Instance (after 42 steps, 0.109s):
                                                                                                                             let x = [8252; 8252; 8252; 8252; 8252]
                                                                                                                            
                                                                                                                            Instance
                                                                                                                            proof attempt
                                                                                                                            ground_instances42
                                                                                                                            definitions0
                                                                                                                            inductions0
                                                                                                                            search_time
                                                                                                                            0.109s
                                                                                                                            details
                                                                                                                            Expand
                                                                                                                            smt_stats
                                                                                                                            arith offset eqs107
                                                                                                                            num checks85
                                                                                                                            arith assert lower408
                                                                                                                            arith pivots254
                                                                                                                            rlimit count84017
                                                                                                                            mk clause870
                                                                                                                            datatype occurs check2446
                                                                                                                            mk bool var4353
                                                                                                                            arith assert upper627
                                                                                                                            datatype splits935
                                                                                                                            decisions2398
                                                                                                                            arith add rows1069
                                                                                                                            arith bound prop49
                                                                                                                            propagations4633
                                                                                                                            interface eqs71
                                                                                                                            conflicts194
                                                                                                                            arith fixed eqs369
                                                                                                                            datatype accessor ax651
                                                                                                                            minimized lits26
                                                                                                                            arith conflicts15
                                                                                                                            arith assert diseq235
                                                                                                                            datatype constructor ax946
                                                                                                                            final checks259
                                                                                                                            added eqs9385
                                                                                                                            del clause684
                                                                                                                            arith eq adapter367
                                                                                                                            memory47.120000
                                                                                                                            max memory47.180000
                                                                                                                            num allocs7202430209.000000
                                                                                                                            Expand
                                                                                                                            • start[0.109s]
                                                                                                                                List.length :var_0: >= 5
                                                                                                                                && is_sorted :var_0: && is_sorted (List.rev :var_0:)
                                                                                                                            • simplify

                                                                                                                              into
                                                                                                                              (List.length :var_0: >= 5 && is_sorted :var_0:)
                                                                                                                              && is_sorted (List.rev :var_0:)
                                                                                                                              expansions
                                                                                                                              []
                                                                                                                              rewrite_steps
                                                                                                                                forward_chaining
                                                                                                                                • unroll
                                                                                                                                  expr
                                                                                                                                  (|List.rev_2678| x_2669)
                                                                                                                                  expansions
                                                                                                                                  • unroll
                                                                                                                                    expr
                                                                                                                                    (is_sorted_2641 (|List.rev_2678| x_2669))
                                                                                                                                    expansions
                                                                                                                                    • unroll
                                                                                                                                      expr
                                                                                                                                      (is_sorted_2641 x_2669)
                                                                                                                                      expansions
                                                                                                                                      • unroll
                                                                                                                                        expr
                                                                                                                                        (|List.length_2675| x_2669)
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (|List.rev_2678| (|get.::.1_2674| x_2669))
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (|List.append_2682|
                                                                                                                                              (|List.rev_2678| (|get.::.1_2674| x_2669))
                                                                                                                                              (|::_3| (|get.::.0_2673| x_2669) …
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.length_2675| (|get.::.1_2674| x_2669))
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| x_2669)))
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (|List.append_2682|
                                                                                                                                                    (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| x_2669)))
                                                                                                                                                    (|::_3| (|get.:…
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (is_sorted_2641 (|get.::.1_2674| (|List.rev_2678| x_2669)))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (|List.length_2675| (|get.::.1_2674| (|get.::.1_2674| x_2669)))
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (is_sorted_2641 (|get.::.1_2674| x_2669))
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (|List.append_2682|
                                                                                                                                                            (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| x_2669)))
                                                                                                                                                            (|::_3| (|get.:…
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (let ((a!1 (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                    (a!…
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (|List.length_2675|
                                                                                                                                                                  (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (is_sorted_2641 (|get.::.1_2674| (|get.::.1_2674| x_2669)))
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                      (|List…
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                            (a!…
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (let ((a!1 (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                          (|List…
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                            (|List…
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (is_sorted_2641 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                (|List…
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                  (|List…
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (is_sorted_2641 (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| x_2669))))
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                      (|List…
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                        (is_so…
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                                              (a!…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                                                (a!…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                              (|List…
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                (|List…
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                                                      (a!…
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                    (|List…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669)))))
                                                                                                                                                                                                          (a!…
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                        (|List…
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                          (|List…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                            (|List…
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                              (|List…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                                (|List…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| x_2669))))))
                                                                                                                                                                                                                  (is_so…
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| (|get.::.1_2674| x_2669))))))
                                                                                                                                                                                                                    (|List…
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2674| (|get.::.1_2674| (|get.::.1_2674| (|List.rev_2678| x_2669))))))
                                                                                                                                                                                                                      (is_so…
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • Sat (Some let x = [8252; 8252; 8252; 8252; 8252] )

                                                                                                                                                                                                                    Proving Merge Sort sorts

                                                                                                                                                                                                                    Now that we've defined our is_sorted predicate, we're ready to state one of our main verification goals: that merge_sort sorts!

                                                                                                                                                                                                                    We can write this this way:

                                                                                                                                                                                                                    theorem merge_sort_sorts x =
                                                                                                                                                                                                                     is_sorted (merge_sort x)
                                                                                                                                                                                                                    

                                                                                                                                                                                                                    Before we try to prove this for all possible cases by induction, let's ask Imandra to verify that this property holds up to our current recursion unrolling bound (100).

                                                                                                                                                                                                                    In [20]:
                                                                                                                                                                                                                    verify (fun x -> is_sorted (merge_sort x))
                                                                                                                                                                                                                    
                                                                                                                                                                                                                    Out[20]:
                                                                                                                                                                                                                    - : int list -> bool = <fun>
                                                                                                                                                                                                                    
                                                                                                                                                                                                                    Unknown (Verified up to bound 100)
                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                    expanded
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl x)))
                                                                                                                                                                                                                    • is_sorted (List.tl (merge_sort x))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds x))
                                                                                                                                                                                                                    • odds x
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • is_sorted (List.tl (List.tl (List.tl (merge_sort x))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds x)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds x)))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds x)))
                                                                                                                                                                                                                    • odds (List.tl x)
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                    • odds (odds x)
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                    • odds (List.tl (odds x))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (odds (odds x))
                                                                                                                                                                                                                    • is_sorted (List.tl (List.tl (merge_sort x)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds x))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl x))
                                                                                                                                                                                                                    • is_sorted (merge_sort x)
                                                                                                                                                                                                                    • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl x))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                    • odds (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge_sort x
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (odds x))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                    • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds x)))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds x)
                                                                                                                                                                                                                    blocked
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (odds (odds …)))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                    • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                    • is_sorted (List.tl (List.tl (List.tl (List.tl (merge_sort x)))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                    • odds (odds (odds (odds …)))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                    • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                    • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                    • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                    • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                    proof attempt
                                                                                                                                                                                                                    ground_instances100
                                                                                                                                                                                                                    definitions0
                                                                                                                                                                                                                    inductions0
                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                    2.369s
                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                    • start[2.369s] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (merge_sort_2605 x_2696)
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (is_sorted_2641 (merge_sort_2605 x_2696))
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (odds_2702 (|get.::.1_2701| x_2696))
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (merge_sort_2605 (odds_2702 (|get.::.1_2701| x_2696)))
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (odds_2702 x_2696)
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (merge_sort_2605 (odds_2702 x_2696))
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (merge_2426 (merge_sort_2605 (odds_2702 x_2696))
                                                                                                                                                                                                                                              (merge_sort_2605 (odds_2702 (|get.::.1_…
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (odds_2702 (|get.::.1_2701| (|get.::.1_2701| x_2696)))
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (odds_2702 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| x_2696))))
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (is_sorted_2641 (|get.::.1_2701| (merge_sort_2605 x_2696)))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (odds_2702 (|get.::.1_2701| (odds_2702 x_2696)))
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (merge_sort_2605 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (odds_2702 (odds_2702 x_2696))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (merge_sort_2605 (odds_2702 (odds_2702 x_2696)))
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (let ((a!1 (merge_sort_2605 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                      (merge_2426 (merge…
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.0_2700| (merge_sort_2605 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                            (a!4 (|ge…
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                          (merge_sort_2605 a…
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (odds_2702 (odds_2702 (|get.::.1_2701| x_2696)))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (merge_sort_2605 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (let ((a!1 (merge_sort_2605 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                    (a!2 (odds_2702…
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (odds_2702 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 x_2696))))
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                    (odds_…
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                      (odds_2702 a…
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                        (odds_…
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                            (merge_sort_2605 a!1))
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (odds_2702 (odds_2702 (odds_2702 x_2696)))
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (merge_sort_2605 (odds_2702 (odds_2702 (odds_2702 x_2696))))
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (is_sorted_2641 (|get.::.1_2701| (|get.::.1_2701| (merge_sort_2605 x_2696))))
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (let ((a!1 (merge_sort_2605 (odds_2702 (odds_2702 (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                        (a!2 (odds_2702 (|get…
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (merge_sort_2605 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                          (a!2 (|get.::.0…
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                        (odds_2702 a!1))
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.0_2700| (merge_sort_2605 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                                              (a!3 (|ge…
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                            (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                (merge_sort_2605 a!1))
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.1_2701|…
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                    (odds_2702 a…
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                      (odds_2702 (…
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                        (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                          (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                            (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                              (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                  (merge_2426 (merge…
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                    (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                        (merge_sort_2605 a!1))
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                                                                              (a!2 (|get.::.1_2701|…
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                                                                                (a!2 (merge_sor…
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                              (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                  (odds_2702 (…
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                    (odds_…
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                      (odds_2702 (…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                        (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                          (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (odds_2702 (odds_2702 (odds_2702 (odds_2702 x_2696))))
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                              (odds_…
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                (merge_sort_2605 a!1))
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.1_2701| (odds…
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (|get.::.1_2701| (merge_sort_2605 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                    (is_so…
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                                                                                          (a!2 (merge_sort_2605…
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                        (odds_2702 (|get.::.1_27…
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (merge_sort_2605 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                                                                                              (a!2 (|get.::.0…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                            (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                              (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                  (merge_2426 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.0_2700| (merge_sort_2605 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                                                                                                                        (a!3 (|ge…
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                      (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                        (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                          (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                            (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                              (odds_2702 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                (odds_2702 (|get.::.1_27…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!2 (merge_so…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                        (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| (odds_2702 x_2696)))))
                                                                                                                                                                                                                                                                                                                                                                                              (a!2 (odds_2702…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                            (odds_2702 (…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                              (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (odds_2702 (|get.::.1_27…
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2702 (odds_2702 (|get.::.1_2701| (odds_2702 x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (merge_2426 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                            (odds_2702 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                              (merge_sort_2605 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2702 (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (merge_2426 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696)))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (a!2 (odds_2702…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2701| (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2702 (…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (odds_2702 (odds_2…
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2701| (odds_2702 (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_2605 (…
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2702 (|get.::.1_2701| (odds_2702 (|get.::.1_2701| x_2696))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (odds_2702 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                                            expansions

                                                                                                                                                                                                                                                                                                                                                                                                                            Excellent. This gives us quite some confidence that this result is true. Let's now try to prove it by induction. We'll want to use an induction principle suggested by the definition of merge_sort. Let's use our usual strategy of #max_induct 1, so we can analyse Imandra's output to help us find needed lemmata.

                                                                                                                                                                                                                                                                                                                                                                                                                            Note, we could prove this theorem directly without any lemmas by using #max_induct 3, but it's good practice to use #max_induct 1 and have Imandra help us develop useful collections of lemmas.

                                                                                                                                                                                                                                                                                                                                                                                                                            In [21]:
                                                                                                                                                                                                                                                                                                                                                                                                                            #max_induct 1
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Out[21]:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            In [22]:
                                                                                                                                                                                                                                                                                                                                                                                                                            theorem merge_sort_sorts x =
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                            [@@induct functional merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Out[22]:
                                                                                                                                                                                                                                                                                                                                                                                                                            val merge_sort_sorts : int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                            Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            is_sorted (merge_sort x).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.030s).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                             && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                    && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                            and merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            This simplifies, using the definition of merge_sort to:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1':
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.026s).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            We can eliminate destructors by the following substitution:
                                                                                                                                                                                                                                                                                                                                                                                                                             x -> x1 :: x2
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1'':
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. is_sorted (merge_sort (odds (x1 :: x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted (merge_sort (odds x2))
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge (merge_sort (odds (x1 :: x2))) (merge_sort (odds x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            This simplifies, using the definition of odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1''':
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted (merge_sort (odds x2))
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted (merge_sort (x1 :: (odds (List.tl x2))))
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                             (merge (merge_sort (x1 :: (odds (List.tl x2)))) (merge_sort (odds x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.034s).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Candidates for generalization:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             merge_sort (odds x2)
                                                                                                                                                                                                                                                                                                                                                                                                                             merge_sort (x1 :: (odds (List.tl x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.042s).
                                                                                                                                                                                                                                                                                                                                                                                                                            This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1'''':
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted gen_1
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted gen_2
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge gen_2 gen_1)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.038s).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Checkpoints:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted gen_1
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted gen_2
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge gen_2 gen_1)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Error: Maximum induction depth reached (1). You can set this with #max_induct.
                                                                                                                                                                                                                                                                                                                                                                                                                            

                                                                                                                                                                                                                                                                                                                                                                                                                            Analysing the output of this proof attempt, we notice the following components of our Checkpoint:

                                                                                                                                                                                                                                                                                                                                                                                                                            H1. is_sorted gen_1
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted gen_2
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge gen_2 gen_1)
                                                                                                                                                                                                                                                                                                                                                                                                                            

                                                                                                                                                                                                                                                                                                                                                                                                                            Ah, of course! We need to prove a lemma that merge respects the sortedness of its inputs.

                                                                                                                                                                                                                                                                                                                                                                                                                            Let's do this by functional induction following the definition of merge and install it as a rewrite rule. We'll allow nested induction (#max_induct 2), but it's a good exercise to do this proof without it (deriving an additional lemma!).

                                                                                                                                                                                                                                                                                                                                                                                                                            In [23]:
                                                                                                                                                                                                                                                                                                                                                                                                                            #max_induct 2;;
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            theorem merge_sorts x y =
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted x && is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                             ==>
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                            [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Out[23]:
                                                                                                                                                                                                                                                                                                                                                                                                                            val merge_sorts : int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                            Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            is_sorted x && is_sorted y ==> is_sorted (merge x y).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Verified up to bound 10 (after 0.035s).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                              && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                             && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> φ y x).
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                            and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted x && is_sorted (List.tl y) ==> is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                            following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2.4:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. List.hd y <= List.hd (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. (List.tl y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H6. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                             H7. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H8. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But we verify Subgoal 1.2.4 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                             H6. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H7. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                            and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H6. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted (List.tl x) && is_sorted y ==> is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                            following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1.4:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. List.hd x <= List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                             H6. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H7. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But we verify Subgoal 1.1.4 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H6. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                            and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                             C2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Subgoal 1.1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                             H0. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             H2. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                             H3. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                             H4. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                             H5. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                            |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                             C0. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                             C1. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                             C2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            
                                                                                                                                                                                                                                                                                                                                                                                                                            Proved
                                                                                                                                                                                                                                                                                                                                                                                                                            proof
                                                                                                                                                                                                                                                                                                                                                                                                                            ground_instances8
                                                                                                                                                                                                                                                                                                                                                                                                                            definitions42
                                                                                                                                                                                                                                                                                                                                                                                                                            inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                            search_time
                                                                                                                                                                                                                                                                                                                                                                                                                            1.364s
                                                                                                                                                                                                                                                                                                                                                                                                                            details
                                                                                                                                                                                                                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                                                                                                                                                                                                                            smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                            num checks10
                                                                                                                                                                                                                                                                                                                                                                                                                            arith assert lower9
                                                                                                                                                                                                                                                                                                                                                                                                                            arith pivots9
                                                                                                                                                                                                                                                                                                                                                                                                                            rlimit count419809
                                                                                                                                                                                                                                                                                                                                                                                                                            mk clause33
                                                                                                                                                                                                                                                                                                                                                                                                                            datatype occurs check20
                                                                                                                                                                                                                                                                                                                                                                                                                            mk bool var103
                                                                                                                                                                                                                                                                                                                                                                                                                            arith assert upper14
                                                                                                                                                                                                                                                                                                                                                                                                                            datatype splits3
                                                                                                                                                                                                                                                                                                                                                                                                                            decisions59
                                                                                                                                                                                                                                                                                                                                                                                                                            arith add rows29
                                                                                                                                                                                                                                                                                                                                                                                                                            propagations72
                                                                                                                                                                                                                                                                                                                                                                                                                            conflicts14
                                                                                                                                                                                                                                                                                                                                                                                                                            datatype accessor ax8
                                                                                                                                                                                                                                                                                                                                                                                                                            arith conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                            arith assert diseq2
                                                                                                                                                                                                                                                                                                                                                                                                                            datatype constructor ax11
                                                                                                                                                                                                                                                                                                                                                                                                                            final checks5
                                                                                                                                                                                                                                                                                                                                                                                                                            added eqs135
                                                                                                                                                                                                                                                                                                                                                                                                                            del clause7
                                                                                                                                                                                                                                                                                                                                                                                                                            arith eq adapter11
                                                                                                                                                                                                                                                                                                                                                                                                                            memory28.610000
                                                                                                                                                                                                                                                                                                                                                                                                                            max memory66.350000
                                                                                                                                                                                                                                                                                                                                                                                                                            num allocs225358809484.000000
                                                                                                                                                                                                                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                                                                                                                                                                                                                            • start[1.364s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                is_sorted :var_0: && is_sorted :var_1:
                                                                                                                                                                                                                                                                                                                                                                                                                                ==> is_sorted (merge :var_0: :var_1:)
                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                              (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              • start[1.364s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                  (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                               && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                           && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                               && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                               ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                              • Split (((((not
                                                                                                                                                                                                                                                                                                                                                                                                                                           (not
                                                                                                                                                                                                                                                                                                                                                                                                                                            ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                            && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                        && (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                               && ((not (is_sorted x) || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge x y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                       && (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                             (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                              && ((not (is_sorted (List.tl x)) || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                       :cases [((((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                               (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                               (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge x y)])
                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                  (((((x = [] || y = []) || List.hd y <= List.hd x) || not (not (is_sorted (List.tl x) && is_sorted y) || is_sorted (merge (List.tl x) y))) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[1.273s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                      (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         || not
                                                                                                                                                                                                                                                                                                                                                                                                                                            (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                      || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                    (((((((((((List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                               || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (List.hd x <= List.hd (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                       || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                      && ((((((((List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                           || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                          || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (((((((merge (List.tl x) y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                               || List.hd x <= List.hd (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                          || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                    && ((((((((is_sorted (merge (List.tl x) y) || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.hd x <= List.hd (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                        || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                    [is_sorted, merge, is_sorted, is_sorted, merge, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                      (((((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (not (is_sorted x && is_sorted (List.tl y)) || is_sorted (merge x (List.tl y)))) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[1.273s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                          (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                        (((((((((((List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (List.hd y <= List.hd (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || List.tl y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                           || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                          && ((((((((List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                         && (((((((merge x (List.tl y) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || List.hd y <= List.hd (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                             || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                        && ((((((((is_sorted (merge x (List.tl y)) || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (List.hd y <= List.hd (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                            || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                        [is_sorted, merge, is_sorted, is_sorted, merge, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          ((((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []) || (List.hd y <= List.hd x && not (y = [])) && not (x = [])) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[1.273s, "1.3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                              ((((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                          • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                            into
                                                                                                                                                                                                                                                                                                                                                                                                                                            true
                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                            [merge, is_sorted, merge, is_sorted, merge, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining

                                                                                                                                                                                                                                                                                                                                                                                                                                        Excellent! Now that we have that key lemma proved and available as a rewrite rule, let's return to our original goal:

                                                                                                                                                                                                                                                                                                                                                                                                                                        In [24]:
                                                                                                                                                                                                                                                                                                                                                                                                                                        theorem merge_sort_sorts x =
                                                                                                                                                                                                                                                                                                                                                                                                                                         is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        [@@induct functional merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Out[24]:
                                                                                                                                                                                                                                                                                                                                                                                                                                        val merge_sort_sorts : int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                        Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        is_sorted (merge_sort x).
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                         is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Verified up to bound 10 (after 0.031s).
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                         (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                             && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                         C0. not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         C1. is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                                        and merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                         is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        This simplifies, using the definition of merge_sort to:
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1.1':
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                         is_sorted (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the rewrite rule merge_sorts.
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                        Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                        proof
                                                                                                                                                                                                                                                                                                                                                                                                                                        ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                        definitions7
                                                                                                                                                                                                                                                                                                                                                                                                                                        inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                        search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                        1.791s
                                                                                                                                                                                                                                                                                                                                                                                                                                        Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[1.791s, "Goal"] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                          is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[1.790s, "1"] is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                          • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                            :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                           && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Split ((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                         && is_sorted (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && is_sorted (merge_sort (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   :cases [not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                           (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((x = [] || List.tl x = [] && x <> []) || not (is_sorted (merge_sort (odds (List.tl x))))) || not (is_sorted (merge_sort (odds x)))) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[1.655s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                (((is_sorted (merge (merge_sort (odds …)) (merge_sort (odds …)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted (merge_sort (odds …))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted (merge_sort (odds …))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || … = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                || … = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                    true
                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                    []
                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                    merge_sorts
                                                                                                                                                                                                                                                                                                                                                                                                                                                    forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    not (List.tl x = [] && x <> []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.655s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                        not (List.tl x = [] && x <> []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                      true
                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                      [is_sorted, merge_sort, is_sorted, merge_sort, is_sorted, merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Beautiful! So now we've proved half of our specification: merge_sort sorts!

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Merge Sort contains the right elements

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Let's now turn to the second half of our correctness criterion: That merge_sort x contains "the same" elements as x.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  What does this mean, and why does it matter?

                                                                                                                                                                                                                                                                                                                                                                                                                                                  An incorrect sorting function

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Consider the sorting function bad_sort defined as bad_sort x = [].

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Clearly, we could prove theorem bad_sort_sorts x = is_sorted (bad_sort x), even though we'd never want to use bad_sort as a sorting function in practice.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  That is, computing a sorted list is only one piece of the puzzle. We must also verify that merge_sort x contains exactly the same elements as x, including their multiplicity).

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Multiset equivalence

                                                                                                                                                                                                                                                                                                                                                                                                                                                  How can we express this concept? We'll use the notion of a multiset and count the number of occurrences of each element of x, and make sure these are respected by merge_sort.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  We'll begin by defining a function num_occurs x y which counts the number of times an element x appears in the list y.

                                                                                                                                                                                                                                                                                                                                                                                                                                                  In [25]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                  let rec num_occurs x y =
                                                                                                                                                                                                                                                                                                                                                                                                                                                   match y with
                                                                                                                                                                                                                                                                                                                                                                                                                                                    | [] -> 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                    | hd :: tl when hd = x ->
                                                                                                                                                                                                                                                                                                                                                                                                                                                      1 + num_occurs x tl
                                                                                                                                                                                                                                                                                                                                                                                                                                                    | _ :: tl ->
                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs x tl
                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Out[25]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                  val num_occurs : 'a -> 'a list -> Z.t = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                  termination proof

                                                                                                                                                                                                                                                                                                                                                                                                                                                  Termination proof

                                                                                                                                                                                                                                                                                                                                                                                                                                                  call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                  originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                  subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  path[y <> [] && List.hd y = x && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                  proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                  detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                  ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                  definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                  inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                  search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                  0.012s
                                                                                                                                                                                                                                                                                                                                                                                                                                                  details
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                  smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                  num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith assert lower9
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith pivots5
                                                                                                                                                                                                                                                                                                                                                                                                                                                  rlimit count753584
                                                                                                                                                                                                                                                                                                                                                                                                                                                  mk clause28
                                                                                                                                                                                                                                                                                                                                                                                                                                                  datatype occurs check29
                                                                                                                                                                                                                                                                                                                                                                                                                                                  mk bool var89
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith assert upper10
                                                                                                                                                                                                                                                                                                                                                                                                                                                  datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                  decisions24
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith add rows11
                                                                                                                                                                                                                                                                                                                                                                                                                                                  propagations45
                                                                                                                                                                                                                                                                                                                                                                                                                                                  conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith fixed eqs8
                                                                                                                                                                                                                                                                                                                                                                                                                                                  datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith assert diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                                                  datatype constructor ax12
                                                                                                                                                                                                                                                                                                                                                                                                                                                  final checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                  added eqs72
                                                                                                                                                                                                                                                                                                                                                                                                                                                  del clause6
                                                                                                                                                                                                                                                                                                                                                                                                                                                  arith eq adapter8
                                                                                                                                                                                                                                                                                                                                                                                                                                                  memory41.630000
                                                                                                                                                                                                                                                                                                                                                                                                                                                  max memory66.350000
                                                                                                                                                                                                                                                                                                                                                                                                                                                  num allocs345333172303.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                  Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.012s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                      (y <> [] && List.hd y = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (y = []) && Ordinal.count y >= 0 && Ordinal.count (List.tl y) >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> not
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                             (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || Ordinal.Int (Ordinal.count (List.tl y)) Ordinal.<<
                                                                                                                                                                                                                                                                                                                                                                                                                                                             Ordinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                     ((((y <> [] && List.hd y = x) && not (y = [])) && Ordinal.count y >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && Ordinal.count (List.tl y) >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                           (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (List.tl y = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || Ordinal.Int (Ordinal.count (List.tl y)) Ordinal.<<
                                                                                                                                                                                                                                                                                                                                                                                                                                                       Ordinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                    []
                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (|Ordinal.<<_121| (|Ordinal.Int_112|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|count_`ty_0 list`_3514| (|get.::.1_3492| …
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|count_`ty_0 list`_3514| (|get.::.1_3492| y_3502))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|count_`ty_0 list`_3514| y_3502)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (th-lemma (or (= |[]_2| y_3502)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not ((_ is (|[]_2| () |`ty_0 li…

                                                                                                                                                                                                                                                                                                                                                                                                                                                            call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                            originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                            subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            path[not (y <> [] && List.hd y = x) && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                            proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                            detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                            ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                            definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                            inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                            search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                            0.014s
                                                                                                                                                                                                                                                                                                                                                                                                                                                            details
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                            smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                            num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith assert lower6
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith pivots4
                                                                                                                                                                                                                                                                                                                                                                                                                                                            rlimit count751154
                                                                                                                                                                                                                                                                                                                                                                                                                                                            mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                                                            datatype occurs check31
                                                                                                                                                                                                                                                                                                                                                                                                                                                            mk bool var67
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith assert upper6
                                                                                                                                                                                                                                                                                                                                                                                                                                                            datatype splits7
                                                                                                                                                                                                                                                                                                                                                                                                                                                            decisions24
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith add rows7
                                                                                                                                                                                                                                                                                                                                                                                                                                                            propagations37
                                                                                                                                                                                                                                                                                                                                                                                                                                                            conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith fixed eqs4
                                                                                                                                                                                                                                                                                                                                                                                                                                                            datatype accessor ax5
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                            datatype constructor ax11
                                                                                                                                                                                                                                                                                                                                                                                                                                                            final checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                            added eqs47
                                                                                                                                                                                                                                                                                                                                                                                                                                                            del clause5
                                                                                                                                                                                                                                                                                                                                                                                                                                                            arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                            memory38.850000
                                                                                                                                                                                                                                                                                                                                                                                                                                                            max memory66.350000
                                                                                                                                                                                                                                                                                                                                                                                                                                                            num allocs344807512501.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[0.014s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                not (y <> [] && List.hd y = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (y = []) && Ordinal.count y >= 0 && Ordinal.count (List.tl y) >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || Ordinal.Int (Ordinal.count (List.tl y)) Ordinal.<<
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Ordinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                                              (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                               (((not (y <> [] && List.hd y = x) && not (y = [])) && Ordinal.count y >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && Ordinal.count (List.tl y) >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (List.tl y = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                              || Ordinal.Int (Ordinal.count (List.tl y)) Ordinal.<<
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 Ordinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                              []
                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (|Ordinal.<<_121| (|Ordinal.Int_112|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (|count_`ty_0 list`_3514| (|get.::.1_3492| …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|count_`ty_0 list`_3514| (|get.::.1_3492| y_3502))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (|count_`ty_0 list`_3514| y_3502)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (= (|count_`ty_0 list`_3514| y_3502)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (+ 1 (|count_`ty_0 list`_3514| (|get.:…

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Anticipating the need to reason about the interplay of num_occurs and merge, let's prove the following nice lemmas characterising their relationship (applying the max_induct 1 strategy to find these lemmas as above is a great exercise).

                                                                                                                                                                                                                                                                                                                                                                                                                                                                      In [26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      theorem num_occur_merge a x y =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Out[26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      val num_occur_merge : int -> int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a (merge x y) = num_occurs a x + num_occurs a y.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Verified up to bound 10 (after 0.035s).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ y x a).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H3. num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a x + num_occurs a (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H3. num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (List.tl x) + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      definitions14
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      0.411s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.411s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs :var_0: (merge :var_1: :var_2:) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs :var_0: :var_1: + num_occurs :var_0: :var_2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[0.410s, "1"] num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • Split (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs a x + num_occurs a (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (merge x y) = num_occurs a x + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x) + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 :cases [((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a (merge x y) = num_occurs a x + num_occurs a y])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((x = [] || y = []) || List.hd y <= List.hd x) || not (num_occurs a (merge (List.tl x) y) = num_occurs a (List.tl x) + num_occurs a y)) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[0.336s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (num_occurs a (merge x (List.tl y)) = num_occurs a x + num_occurs a (List.tl y))) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[0.336s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []) || (List.hd y <= List.hd x && not (y = [])) && not (x = [])) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.336s, "1.3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [num_occurs, merge, num_occurs, merge, num_occurs, merge, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  In [27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  theorem num_occurs_arith (x : int list) (a : int) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs a x - num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [@@induct functional num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Out[27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  val num_occurs_arith : int list -> int -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> num_occurs a (odds (List.tl x)) = num_occurs a x - num_occurs a (odds x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This simplifies, using the definition of num_occurs to the following 2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x) + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Verified up to bound 10 (after 0.027s).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  We can eliminate destructors by the following substitution:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   x -> x1 :: x2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.2':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a x2 + -1 * num_occurs a (odds (x1 :: x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. x1 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This simplifies, using the definitions of num_occurs and odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.2'':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. x1 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a x2 + -1 * num_occurs a (odds (List.tl x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This simplifies, using the definition of num_occurs to the following 2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.2''.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x2) + -1 * num_occurs a (odds (List.tl x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd x2 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C2. x1 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Verified up to bound 10 (after 0.029s).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Note: We must proceed by induction, but our current subgoal is less
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  appropriate for induction than our original conjecture. Thus, we prefer to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  abandon our work until now and return our focus to the original conjecture
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  which we shall attempt to prove by induction directly.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  We shall induct according to a scheme derived from num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (not (x <> [] && List.hd x = a) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not (x = []) && not (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (not (x = []) && (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. not (not (x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. not (x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. not (List.tl x = []) && not (List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (List.tl x) + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H4. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 2.4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (1 + num_occurs a (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H4. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (List.tl (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs a (List.tl (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (-1 + num_occurs a (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. not (List.tl x = []) && not (List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (List.tl x) + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H4. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H5. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. num_occurs (List.hd x) (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs (List.hd x) (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs (List.hd x) (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. num_occurs (List.hd x) (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (1 + num_occurs (List.hd x) (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs (List.hd x) (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H4. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C0. num_occurs (List.hd x) (List.tl (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   C1. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H0. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs (List.hd x) (List.tl (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (-1 + num_occurs (List.hd x) (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  definitions48
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1.666s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[1.666s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      not (:var_0: = []) && not (List.tl :var_0: = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> num_occurs :var_1: (odds (List.tl :var_0:)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs :var_1: :var_0: - num_occurs :var_1: (odds :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (x = [] || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.665s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x) + -1 * num_occurs a (odds x) || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (((num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ((num_occurs a (odds (List.tl x)) = (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x) || not (List.hd x = a)) || List.tl x = []) || x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            start[1.591s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ((num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ((num_occurs a (odds (List.tl x)) = num_occurs a (List.tl x) + -1 * num_occurs a (odds x) || List.hd x = a) || List.tl x = []) || x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[1.591s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ((num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs a (List.tl x) + -1 * num_occurs a (odds x) || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Elim_destructor (:cstor :: :replace x1 :: x2 :context [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (x1 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs a x2 + -1 * num_occurs a (odds (List.tl x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (x2 <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [num_occurs, odds]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (List.tl x2) + -1 * num_occurs a (odds (List.tl x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.hd x2 = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || x1 = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (x2 <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (((num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (1 + num_occurs a (List.tl x2)) + -1 * num_occurs a (odds (List.tl x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (List.hd x2 = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || x1 = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || not (x2 <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Finally, let's put the pieces together and prove our main remaining theorem.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              And now, our second main theorem at last:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              In [28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              theorem merge_sort_elements a (x : int list) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [@@induct functional merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Out[28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              val merge_sort_elements : int -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a x = num_occurs a (merge_sort x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Verified up to bound 10 (after 0.029s).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && φ (odds (List.tl x)) a && φ (odds x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ x a).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C0. not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C1. num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definitions of merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              and num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H3. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definitions of merge_sort and num_occurs, and the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite rule num_occurs_arith to the following 2 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C0. num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the rewrite rule
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occur_merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   -1 + num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H3. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H4. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               -1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + num_occurs a (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the rewrite rule
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occur_merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              definitions14
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              14.640s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[14.640s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs :var_0: :var_1: = num_occurs :var_0: (merge_sort :var_1:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[14.640s, "1"] num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && φ (odds (List.tl x)) a && φ (odds x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Split ((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a x = num_occurs a (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs a (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && num_occurs a (odds x) = num_occurs a (merge_sort (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a x = num_occurs a (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         :cases [not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || num_occurs a x = num_occurs a (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || num_occurs a x = num_occurs a (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((x = [] || List.tl x = [] && x <> []) || not (num_occurs a (odds (List.tl x)) = num_occurs a (merge_sort (odds (List.tl x))))) || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x)))) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[14.520s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((((num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (((((num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              -1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              + num_occurs a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 -1 + num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [merge_sort, num_occurs, merge_sort, num_occurs, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs_arith
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      not (List.tl x = [] && x <> []) && not (x = []) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[14.520s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [num_occurs, merge_sort, num_occurs, num_occurs, merge_sort, num_occurs,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs, merge_sort, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    So now we're sure merge_sort really is a proper sorting function.

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Merge Sort is Correct!

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    To recap, we've proved:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem merge_sort_sorts x =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    and

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem merge_sort_elements a (x : int list) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Beautiful! Happy proving (and sorting)!