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
definitions0
inductions0
search_time
0.033s
details
Expand
smt_stats
arith offset eqs34
num checks18
arith assert lower153
arith pivots81
rlimit count71871
mk clause242
datatype occurs check261
mk bool var599
arith assert upper153
datatype splits47
decisions375
arith add rows264
arith bound prop15
propagations599
interface eqs4
conflicts46
arith fixed eqs98
datatype accessor ax61
minimized lits3
arith conflicts8
arith assert diseq18
datatype constructor ax80
num allocs1050881562
final checks29
added eqs836
del clause150
arith eq adapter110
memory26.040000
max memory26.950000
Expand
  • start[0.033s]
      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 = []))
          || Ordinal.( << )
             (if [Ordinal.Int (Ordinal.count (List.tl l));
                  Ordinal.Int (Ordinal.count m)]
                 = []
              then Ordinal.Int 0
              else
              if true
                 && List.tl
                    [Ordinal.Int (Ordinal.count (List.tl l));
                     Ordinal.Int (Ordinal.count m)]
                    = []
              then
                List.hd
                [Ordinal.Int (Ordinal.count (List.tl l));
                 Ordinal.Int (Ordinal.count m)]
              else
              if true
                 && (List.tl
                     [Ordinal.Int (Ordinal.count (List.tl l));
                      Ordinal.Int (Ordinal.count m)]) <> []
                    && List.tl
                       (List.tl
                        [Ordinal.Int (Ordinal.count (List.tl l));
                         Ordinal.Int (Ordinal.count m)])
                       = []
              then … else …)
             (if [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)] =
                 []
              then Ordinal.Int 0
              else
              if true
                 && List.tl
                    [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
                    = []
              then
                List.hd
                [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
              else
              if true
                 && (List.tl
                     [Ordinal.Int (Ordinal.count l);
                      Ordinal.Int (Ordinal.count m)]) <> []
                    && List.tl
                       (List.tl
                        [Ordinal.Int (Ordinal.count l);
                         Ordinal.Int (Ordinal.count m)])
                       = []
              then … else …)
  • 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.( << )
       (Ordinal.plus
        (Ordinal.shift (Ordinal.Int (Ordinal.count (List.tl l))) (Ordinal.Int 1))
        (Ordinal.Int (Ordinal.count m)))
       (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_127|
          (|Ordinal.Int_93| (|count_`int list`_1894| l_1881))
          (|Ordinal.Int_93| 1))
        expansions
        • unroll
          expr
          (|Ordinal.plus_113|
            (|Ordinal.shift_127|
              (|Ordinal.Int_93| (|count_`int list`_1894| l_1881))
           …
          expansions
          • unroll
            expr
            (|Ordinal.shift_127|
              (|Ordinal.Int_93| (|count_`int list`_1894| (|get.::.1_1880| l_1881)))
              (|Ord…
            expansions
            • unroll
              expr
              (let ((a!1 (|Ordinal.shift_127|
                           (|Ordinal.Int_93| (|count_`int list`_1894|
                          …
              expansions
              • unroll
                expr
                (let ((a!1 (|Ordinal.shift_127|
                             (|Ordinal.Int_93| (|count_`int list`_1894|
                            …
                expansions
                • unroll
                  expr
                  (|count_`int list`_1894| (|get.::.1_1880| l_1881))
                  expansions
                  • unroll
                    expr
                    (|count_`int list`_1894| m_1882)
                    expansions
                    • unroll
                      expr
                      (|count_`int list`_1894| l_1881)
                      expansions
                      • unsat
                        (let ((a!1 (|Ordinal.shift_127|
                                     (|Ordinal.Int_93| (|count_`int list`_1894|
                                    …

                      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_instances16
                      definitions0
                      inductions0
                      search_time
                      0.053s
                      details
                      Expand
                      smt_stats
                      arith offset eqs92
                      num checks34
                      arith assert lower475
                      arith pivots155
                      rlimit count52722
                      mk clause665
                      datatype occurs check844
                      mk bool var1709
                      arith assert upper492
                      datatype splits141
                      decisions1363
                      arith add rows572
                      arith bound prop23
                      propagations2098
                      interface eqs8
                      conflicts72
                      arith fixed eqs269
                      datatype accessor ax211
                      minimized lits15
                      arith conflicts9
                      arith assert diseq48
                      datatype constructor ax299
                      num allocs1014019775
                      final checks60
                      added eqs2575
                      del clause307
                      arith eq adapter417
                      memory22.590000
                      max memory26.950000
                      Expand
                      • start[0.053s]
                          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 = []))
                              || Ordinal.( << )
                                 (if [Ordinal.Int (Ordinal.count l);
                                      Ordinal.Int (Ordinal.count (List.tl m))]
                                     = []
                                  then Ordinal.Int 0
                                  else
                                  if true
                                     && List.tl
                                        [Ordinal.Int (Ordinal.count l);
                                         Ordinal.Int (Ordinal.count (List.tl m))]
                                        = []
                                  then
                                    List.hd
                                    [Ordinal.Int (Ordinal.count l);
                                     Ordinal.Int (Ordinal.count (List.tl m))]
                                  else
                                  if true
                                     && (List.tl
                                         [Ordinal.Int (Ordinal.count l);
                                          Ordinal.Int (Ordinal.count (List.tl m))]) <> []
                                        && List.tl
                                           (List.tl
                                            [Ordinal.Int (Ordinal.count l);
                                             Ordinal.Int (Ordinal.count (List.tl m))])
                                           = []
                                  then … else …)
                                 (if [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)] =
                                     []
                                  then Ordinal.Int 0
                                  else
                                  if true
                                     && List.tl
                                        [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
                                        = []
                                  then
                                    List.hd
                                    [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
                                  else
                                  if true
                                     && (List.tl
                                         [Ordinal.Int (Ordinal.count l);
                                          Ordinal.Int (Ordinal.count m)]) <> []
                                        && List.tl
                                           (List.tl
                                            [Ordinal.Int (Ordinal.count l);
                                             Ordinal.Int (Ordinal.count m)])
                                           = []
                                  then … else …)
                      • 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.( << )
                           (Ordinal.plus
                            (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
                            (Ordinal.Int (Ordinal.count (List.tl m))))
                           (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_113|
                              (|Ordinal.shift_127|
                                (|Ordinal.Int_93| (|count_`int list`_1894| l_1881))
                             …
                            expansions
                            • unroll
                              expr
                              (|Ordinal.shift_127|
                                (|Ordinal.Int_93| (|count_`int list`_1894| l_1881))
                                (|Ordinal.Int_93| 1))
                              expansions
                              • unroll
                                expr
                                (|Ordinal.plus_113|
                                  (|Ordinal.shift_127|
                                    (|Ordinal.Int_93| (|count_`int list`_1894| l_1881))
                                 …
                                expansions
                                • unroll
                                  expr
                                  (let ((a!1 (|Ordinal.plus_113|
                                               (|Ordinal.shift_127|
                                                 (|Ordinal.Int_93| (|…
                                  expansions
                                  • unroll
                                    expr
                                    (|count_`int list`_1894| (|get.::.1_1880| m_1882))
                                    expansions
                                    • unroll
                                      expr
                                      (|count_`int list`_1894| m_1882)
                                      expansions
                                      • unroll
                                        expr
                                        (|count_`int list`_1894| l_1881)
                                        expansions
                                        • unroll
                                          expr
                                          (|count_`int list`_1894| (|get.::.1_1880| l_1881))
                                          expansions
                                          • unroll
                                            expr
                                            (|count_`int list`_1894| (|get.::.1_1880| (|get.::.1_1880| m_1882)))
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|get.Ordinal.Cons.2_1887|
                                                           (|Ordinal.shift_127|
                                                             (|Ordinal.Int…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|get.Ordinal.Cons.0_1885|
                                                             (|Ordinal.shift_127|
                                                               (|Ordinal.Int…
                                                expansions
                                                • unroll
                                                  expr
                                                  (let ((a!1 (|get.Ordinal.Cons.2_1887|
                                                               (|Ordinal.shift_127|
                                                                 (|Ordinal.Int…
                                                  expansions
                                                  • unroll
                                                    expr
                                                    (let ((a!1 (|get.Ordinal.Cons.0_1885|
                                                                 (|Ordinal.shift_127|
                                                                   (|Ordinal.Int…
                                                    expansions
                                                    • unroll
                                                      expr
                                                      (let ((a!1 (|Ordinal.plus_113|
                                                                   (|Ordinal.shift_127|
                                                                     (|Ordinal.Int_93| (|…
                                                      expansions
                                                      • unroll
                                                        expr
                                                        (|Ordinal.shift_127|
                                                          (|get.Ordinal.Cons.2_1887|
                                                            (|Ordinal.Int_93| (|count_`int list`_1894| l_1…
                                                        expansions
                                                        • unroll
                                                          expr
                                                          (let ((a!1 (|Ordinal.plus_113|
                                                                       (|Ordinal.shift_127|
                                                                         (|Ordinal.Int_93| (|…
                                                          expansions
                                                          • unsat
                                                            (let ((a!1 (>= (ite (>= (|get.::.0_1879| m_1882) 0) (|get.::.0_1879| m_1882) 0)
                                                                           0))
                                                             …

                                                          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 (l <> [] && List.tl l = []) && not (l = [])]
                                                          proof
                                                          detailed proof
                                                          ground_instances6
                                                          definitions0
                                                          inductions0
                                                          search_time
                                                          0.017s
                                                          details
                                                          Expand
                                                          smt_stats
                                                          arith offset eqs4
                                                          num checks14
                                                          arith assert lower27
                                                          arith pivots16
                                                          rlimit count5762
                                                          mk clause73
                                                          datatype occurs check45
                                                          mk bool var174
                                                          arith assert upper26
                                                          datatype splits11
                                                          decisions51
                                                          arith add rows37
                                                          arith bound prop5
                                                          propagations47
                                                          interface eqs1
                                                          conflicts18
                                                          arith fixed eqs23
                                                          datatype accessor ax11
                                                          minimized lits1
                                                          arith conflicts3
                                                          arith assert diseq3
                                                          datatype constructor ax21
                                                          num allocs1132917850
                                                          final checks12
                                                          added eqs113
                                                          del clause21
                                                          arith eq adapter20
                                                          memory27.280000
                                                          max memory27.280000
                                                          Expand
                                                          • start[0.017s]
                                                              not (l <> [] && List.tl l = [])
                                                              && not (l = [])
                                                                 && Ordinal.count l >= 0 && Ordinal.count (List.tl (List.tl l)) >= 0
                                                              ==> not
                                                                  (not
                                                                   ((List.tl (List.tl l)) <> [] && List.tl (List.tl (List.tl l)) = [])
                                                                   && not (List.tl (List.tl l) = []))
                                                                  || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl (List.tl l))))
                                                                     (Ordinal.Int (Ordinal.count l))
                                                          • simplify
                                                            into
                                                            (not
                                                             (((not (l <> [] && List.tl l = []) && not (l = [])) && Ordinal.count l >= 0)
                                                              && Ordinal.count (List.tl (List.tl l)) >= 0)
                                                             || not
                                                                (not ((List.tl (List.tl l)) <> [] && List.tl (List.tl (List.tl l)) = [])
                                                                 && not (List.tl (List.tl l) = [])))
                                                            || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl (List.tl l))))
                                                               (Ordinal.Int (Ordinal.count l))
                                                            expansions
                                                            []
                                                            rewrite_steps
                                                              forward_chaining
                                                              • unroll
                                                                expr
                                                                (let ((a!1 (|Ordinal.Int_93| (|count_`ty_0 list`_1934|
                                                                                               (|get.::.1_191…
                                                                expansions
                                                                • unroll
                                                                  expr
                                                                  (|count_`ty_0 list`_1934| (|get.::.1_1918| (|get.::.1_1918| l_1925)))
                                                                  expansions
                                                                  • unroll
                                                                    expr
                                                                    (|count_`ty_0 list`_1934| l_1925)
                                                                    expansions
                                                                    • unroll
                                                                      expr
                                                                      (|count_`ty_0 list`_1934|
                                                                        (|get.::.1_1918| (|get.::.1_1918| (|get.::.1_1918| l_1925))))
                                                                      expansions
                                                                      • unroll
                                                                        expr
                                                                        (let ((a!1 (|Ordinal.Int_93| (|count_`ty_0 list`_1934|
                                                                                                       (|get.::.1_191…
                                                                        expansions
                                                                        • unroll
                                                                          expr
                                                                          (|count_`ty_0 list`_1934| (|get.::.1_1918| l_1925))
                                                                          expansions
                                                                          • unsat
                                                                            (let ((a!1 (ite (>= (|count_`ty_0 list`_1934| (|get.::.1_1918| l_1925)) 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]:
                                                                          - : int list = [1; 3; 5]
                                                                          
                                                                          In [7]:
                                                                          odds (List.tl [1;2;3;4;5;6])
                                                                          
                                                                          Out[7]:
                                                                          - : int 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-129Error: 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 (l <> [] && List.tl l = []) and not (l = [])
                                                                          could not be proved to decrease (measured subset: (l))
                                                                          See https://docs.imandra.ai/imandra-docs/notebooks/proving-program-termination/
                                                                          

                                                                          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.
                                                                          
                                                                          We shall induct according to a scheme derived from odds.
                                                                          
                                                                          Induction scheme:
                                                                          
                                                                           (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                           && (not (x = [])
                                                                               && not (x <> [] && List.tl 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 (x <> [] && List.tl x = []) && not (x = [])
                                                                          
                                                                          But simplification reduces this to true, using the forward-chaining rule
                                                                          List.len_nonnegative.
                                                                          
                                                                          Subgoal 1:
                                                                          
                                                                           H0. not (x = [])
                                                                           H1. not (x <> [] && List.tl 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. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. List.tl (List.tl x) = []
                                                                           H3. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          But simplification reduces this to true, using the definitions of List.length
                                                                          and odds.
                                                                          
                                                                          Subgoal 1.2:
                                                                          
                                                                           H0. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. (List.tl (List.tl x)) <> []
                                                                           H3. (List.tl (List.tl (List.tl x))) <> []
                                                                           H4. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                          |---------------------------------------------------------------------------
                                                                           List.length (List.tl (List.tl x)) <=
                                                                           List.length (odds (List.tl (List.tl x)))
                                                                          
                                                                          This simplifies, using the definition of List.length to:
                                                                          
                                                                          Subgoal 1.2':
                                                                          
                                                                           H0. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. (List.tl (List.tl x)) <> []
                                                                           H3. (List.tl (List.tl (List.tl x))) <> []
                                                                           H4. List.length (List.tl (List.tl x)) <=
                                                                               (-1 + List.length (odds (List.tl (List.tl x))))
                                                                          |---------------------------------------------------------------------------
                                                                           List.length (List.tl (List.tl (List.tl x))) <=
                                                                           (-1 + List.length (odds (List.tl (List.tl x))))
                                                                          
                                                                          But simplification reduces this to true, using the definition of List.length.
                                                                          
                                                                          Subgoal 1.1:
                                                                          
                                                                           H0. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. (List.tl (List.tl x)) <> []
                                                                           H3. List.tl (List.tl (List.tl x)) = []
                                                                           H4. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          This simplifies, using the definitions of List.length and odds to:
                                                                          
                                                                          Subgoal 1.1':
                                                                          
                                                                           H0. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. (List.tl (List.tl x)) <> []
                                                                           H3. List.tl (List.tl (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.
                                                                          
                                                                           Rules:
                                                                              (:def List.length)
                                                                              (:def odds)
                                                                              (:fc List.len_nonnegative)
                                                                              (:induct odds)
                                                                          
                                                                          
                                                                          Proved
                                                                          proof
                                                                          ground_instances0
                                                                          definitions13
                                                                          inductions1
                                                                          search_time
                                                                          0.591s
                                                                          Expand
                                                                          • start[0.591s, "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.591s, "1"]
                                                                                (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                            • induction on (functional odds)
                                                                              :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                      && (not (x = [])
                                                                                          && not (x <> [] && List.tl x = []) && φ (List.tl (List.tl x))
                                                                                          ==> φ x)
                                                                            • Split (((not (x <> [] && List.tl x = []) && not (x = [])
                                                                                       || not (not (x = []) && not (List.tl x = [])))
                                                                                      || not (List.length x <= List.length (odds x)))
                                                                                     && ((not
                                                                                          ((not (x = []) && not (x <> [] && List.tl 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 (x <> [] && List.tl x = []) && not (x = []);
                                                                                             ((((x = [] || x <> [] && List.tl 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))))))
                                                                                               || x = [])
                                                                                              || List.tl x = [])
                                                                                             || not (List.length x <= List.length (odds x))])
                                                                              • subproof
                                                                                ((((x = [] || x <> [] && List.tl 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)))))) || x = []) || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                                • start[0.590s, "1"]
                                                                                    ((((x = [] || x <> [] && List.tl 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))))))
                                                                                      || x = [])
                                                                                     || List.tl x = [])
                                                                                    || not (List.length x <= List.length (odds x))
                                                                                • simplify
                                                                                  into
                                                                                  ((((x = [] || List.tl x = []) || not (List.tl (List.tl x) = []))
                                                                                    || not
                                                                                       (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))))
                                                                                   && (((((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)) = [])
                                                                                       || not
                                                                                          (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x))))))
                                                                                  && ((((x = [] || List.tl x = []) || List.tl (List.tl x) = [])
                                                                                       || not (List.tl (List.tl (List.tl x)) = []))
                                                                                      || not
                                                                                         (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))))
                                                                                  expansions
                                                                                  [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
                                                                                    • Subproof
                                                                                    • Subproof
                                                                                    • Subproof
                                                                                • subproof
                                                                                  ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))) || not (x <> [] && List.tl x = []) && not (x = [])
                                                                                  • start[0.590s, "2"]
                                                                                      ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x)))
                                                                                      || not (x <> [] && List.tl 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 (l <> [] && List.tl l = []) && not (l = [])]
                                                                              proof
                                                                              detailed proof
                                                                              ground_instances1
                                                                              definitions0
                                                                              inductions0
                                                                              search_time
                                                                              0.017s
                                                                              details
                                                                              Expand
                                                                              smt_stats
                                                                              num checks3
                                                                              arith assert lower3
                                                                              arith pivots1
                                                                              rlimit count5537
                                                                              mk clause3
                                                                              datatype occurs check28
                                                                              mk bool var51
                                                                              datatype splits9
                                                                              decisions15
                                                                              propagations3
                                                                              conflicts8
                                                                              datatype accessor ax7
                                                                              datatype constructor ax13
                                                                              final checks6
                                                                              added eqs39
                                                                              del clause3
                                                                              memory48.400000
                                                                              max memory55.490000
                                                                              num allocs7115314836.000000
                                                                              Expand
                                                                              • start[0.017s]
                                                                                  not (l <> [] && List.tl 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 ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = []))
                                                                                      && not
                                                                                         (not ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = []))
                                                                                      || Ordinal.( << )
                                                                                         (Ordinal.Int
                                                                                          (if List.length (odds l) >= 0 then List.length (odds l) else 0))
                                                                                         (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                              • simplify
                                                                                into
                                                                                (not
                                                                                 (((not (l <> [] && List.tl 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 ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = [])))
                                                                                || Ordinal.( << )
                                                                                   (Ordinal.Int
                                                                                    (if List.length (odds l) >= 0 then List.length (odds l) else 0))
                                                                                   (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_2200| (odds_2204 l_2210)) 0)
                                                                                                    (|List.length_2200| (…
                                                                                    expansions
                                                                                    • unsat
                                                                                      (let ((a!1 (and (not (= l_2210 |[]_2|))
                                                                                                      (not (= (|get.::.1_2193| l_2210) |[]_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 (l <> [] && List.tl l = []) && not (l = [])]
                                                                                    proof
                                                                                    detailed proof
                                                                                    ground_instances4
                                                                                    definitions0
                                                                                    inductions0
                                                                                    search_time
                                                                                    0.021s
                                                                                    details
                                                                                    Expand
                                                                                    smt_stats
                                                                                    num checks10
                                                                                    arith assert lower6
                                                                                    arith pivots6
                                                                                    rlimit count3621
                                                                                    mk clause16
                                                                                    datatype occurs check83
                                                                                    mk bool var121
                                                                                    arith assert upper14
                                                                                    datatype splits25
                                                                                    decisions42
                                                                                    arith add rows8
                                                                                    propagations35
                                                                                    conflicts15
                                                                                    datatype accessor ax12
                                                                                    arith conflicts1
                                                                                    datatype constructor ax27
                                                                                    final checks18
                                                                                    added eqs100
                                                                                    del clause8
                                                                                    arith eq adapter2
                                                                                    memory45.470000
                                                                                    max memory55.490000
                                                                                    num allocs7002549358.000000
                                                                                    Expand
                                                                                    • start[0.021s]
                                                                                        not (l <> [] && List.tl 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 ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                             && not (odds (List.tl l) = []))
                                                                                            && not
                                                                                               (not ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                                && not (odds (List.tl l) = []))
                                                                                            || Ordinal.( << )
                                                                                               (Ordinal.Int
                                                                                                (if List.length (odds (List.tl l)) >= 0
                                                                                                 then List.length (odds (List.tl l)) else 0))
                                                                                               (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                                    • simplify
                                                                                      into
                                                                                      (not
                                                                                       (((not (l <> [] && List.tl 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 ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                           && not (odds (List.tl l) = [])))
                                                                                      || Ordinal.( << )
                                                                                         (Ordinal.Int
                                                                                          (if List.length (odds (List.tl l)) >= 0
                                                                                           then List.length (odds (List.tl l)) else 0))
                                                                                         (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_2200| (odds_2204 (|get.::.1_2193| l_2210))) 0))
                                                                                                (a!3 (|Ordinal.In…
                                                                                          expansions
                                                                                          • unroll
                                                                                            expr
                                                                                            (odds_2204 (|get.::.1_2193| l_2210))
                                                                                            expansions
                                                                                            • unroll
                                                                                              expr
                                                                                              (|List.length_2200| (odds_2204 (|get.::.1_2193| l_2210)))
                                                                                              expansions
                                                                                              • unroll
                                                                                                expr
                                                                                                (|List.length_2200| l_2210)
                                                                                                expansions
                                                                                                • unsat
                                                                                                  (let ((a!1 (not (and ((_ is (|::_3| (Int |`int list`_2191|) |`int list`_2191|))
                                                                                                                      …

                                                                                                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 (x <> [] && List.tl x = []) && not (x = [])]
                                                                                                proof
                                                                                                detailed proof
                                                                                                ground_instances3
                                                                                                definitions0
                                                                                                inductions0
                                                                                                search_time
                                                                                                0.025s
                                                                                                details
                                                                                                Expand
                                                                                                smt_stats
                                                                                                num checks8
                                                                                                arith assert lower26
                                                                                                arith pivots9
                                                                                                rlimit count3044
                                                                                                mk clause32
                                                                                                datatype occurs check34
                                                                                                mk bool var109
                                                                                                arith assert upper16
                                                                                                datatype splits11
                                                                                                decisions23
                                                                                                arith add rows17
                                                                                                arith bound prop1
                                                                                                propagations24
                                                                                                interface eqs3
                                                                                                conflicts11
                                                                                                arith fixed eqs12
                                                                                                datatype accessor ax6
                                                                                                arith conflicts2
                                                                                                arith assert diseq2
                                                                                                datatype constructor ax10
                                                                                                final checks12
                                                                                                added eqs67
                                                                                                del clause16
                                                                                                arith eq adapter16
                                                                                                memory46.340000
                                                                                                max memory55.490000
                                                                                                num allocs7419736438.000000
                                                                                                Expand
                                                                                                • start[0.025s]
                                                                                                    List.hd x <= List.hd (List.tl x)
                                                                                                    && not (x <> [] && List.tl 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 x) <> [] && List.tl (List.tl x) = [])
                                                                                                            && not (List.tl x = []))
                                                                                                        || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                                           (Ordinal.Int (Ordinal.count x))
                                                                                                • simplify
                                                                                                  into
                                                                                                  (not
                                                                                                   ((((List.hd x <= List.hd (List.tl x) && not (x <> [] && List.tl 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 x) <> [] && List.tl (List.tl x) = []))
                                                                                                       && not (List.tl x = [])))
                                                                                                  || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                                     (Ordinal.Int (Ordinal.count x))
                                                                                                  expansions
                                                                                                  []
                                                                                                  rewrite_steps
                                                                                                    forward_chaining
                                                                                                    • unroll
                                                                                                      expr
                                                                                                      (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`int list`_2235|
                                                                                                                                            (…
                                                                                                      expansions
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (|count_`int list`_2235| (|get.::.1_2225| x_2226))
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|count_`int list`_2235| x_2226)
                                                                                                          expansions
                                                                                                          • unsat
                                                                                                            (let ((a!1 (>= (ite (>= (|get.::.0_2224| x_2226) 0) (|get.::.0_2224| x_2226) 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 : int list end
                                                                                                          
                                                                                                          Instance (after 11 steps, 0.030s):
                                                                                                           let (x : int list) = [7719; 7719; 16574; 18856; 24709]
                                                                                                          
                                                                                                          Instance
                                                                                                          proof attempt
                                                                                                          ground_instances11
                                                                                                          definitions0
                                                                                                          inductions0
                                                                                                          search_time
                                                                                                          0.031s
                                                                                                          details
                                                                                                          Expand
                                                                                                          smt_stats
                                                                                                          num checks23
                                                                                                          arith assert lower60
                                                                                                          arith pivots27
                                                                                                          rlimit count8879
                                                                                                          mk clause104
                                                                                                          datatype occurs check69
                                                                                                          mk bool var315
                                                                                                          arith assert upper38
                                                                                                          datatype splits35
                                                                                                          decisions94
                                                                                                          arith add rows128
                                                                                                          propagations201
                                                                                                          interface eqs1
                                                                                                          conflicts36
                                                                                                          arith fixed eqs35
                                                                                                          datatype accessor ax24
                                                                                                          arith conflicts11
                                                                                                          arith assert diseq10
                                                                                                          datatype constructor ax42
                                                                                                          final checks36
                                                                                                          added eqs307
                                                                                                          del clause72
                                                                                                          arith eq adapter38
                                                                                                          memory47.080000
                                                                                                          max memory55.490000
                                                                                                          num allocs7638736219.000000
                                                                                                          Expand
                                                                                                          • start[0.031s] List.length :var_0: >= 5 && is_sorted :var_0:
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (is_sorted_41 x_46)
                                                                                                            expansions
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (|List.length_2242| x_46)
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (|List.length_2242| (|get.::.1_2241| x_46))
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (|List.length_2242| (|get.::.1_2241| (|get.::.1_2241| x_46)))
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (is_sorted_41 (|get.::.1_2241| x_46))
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (|List.length_2242| (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| x_46))))
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (is_sorted_41 (|get.::.1_2241| (|get.::.1_2241| x_46)))
                                                                                                                        expansions
                                                                                                                        • unroll
                                                                                                                          expr
                                                                                                                          (let ((a!1 (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| x_46))))))
                                                                                                                            (|List.l…
                                                                                                                          expansions
                                                                                                                          • unroll
                                                                                                                            expr
                                                                                                                            (is_sorted_41 (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| x_46))))
                                                                                                                            expansions
                                                                                                                            • unroll
                                                                                                                              expr
                                                                                                                              (let ((a!1 (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| x_46))))))
                                                                                                                                (|List.l…
                                                                                                                              expansions
                                                                                                                              • unroll
                                                                                                                                expr
                                                                                                                                (let ((a!1 (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| (|get.::.1_2241| x_46))))))
                                                                                                                                  (is_sort…
                                                                                                                                expansions
                                                                                                                                • Sat (Some let (x : int list) = [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 : int list end
                                                                                                                                
                                                                                                                                Instance (after 44 steps, 0.109s):
                                                                                                                                 let (x : int list) = [1733; 1733; 1733; 1733; 1733]
                                                                                                                                
                                                                                                                                Instance
                                                                                                                                proof attempt
                                                                                                                                ground_instances44
                                                                                                                                definitions0
                                                                                                                                inductions0
                                                                                                                                search_time
                                                                                                                                0.109s
                                                                                                                                details
                                                                                                                                Expand
                                                                                                                                smt_stats
                                                                                                                                arith offset eqs145
                                                                                                                                num checks89
                                                                                                                                arith assert lower553
                                                                                                                                arith pivots391
                                                                                                                                rlimit count108884
                                                                                                                                mk clause1094
                                                                                                                                datatype occurs check2466
                                                                                                                                mk bool var5164
                                                                                                                                arith assert upper674
                                                                                                                                datatype splits1056
                                                                                                                                decisions2445
                                                                                                                                arith add rows2041
                                                                                                                                arith bound prop34
                                                                                                                                propagations6197
                                                                                                                                interface eqs98
                                                                                                                                conflicts214
                                                                                                                                arith fixed eqs482
                                                                                                                                datatype accessor ax760
                                                                                                                                minimized lits67
                                                                                                                                arith conflicts32
                                                                                                                                arith assert diseq138
                                                                                                                                datatype constructor ax1035
                                                                                                                                final checks288
                                                                                                                                added eqs11638
                                                                                                                                del clause848
                                                                                                                                arith eq adapter554
                                                                                                                                memory48.600000
                                                                                                                                max memory55.490000
                                                                                                                                num allocs7892349114.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_2255| x_48)
                                                                                                                                      expansions
                                                                                                                                      • unroll
                                                                                                                                        expr
                                                                                                                                        (is_sorted_41 (|List.rev_2255| x_48))
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (is_sorted_41 x_48)
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (|List.length_2252| x_48)
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.rev_2255| (|get.::.1_2251| x_48))
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (|List.append_2259|
                                                                                                                                                  (|List.rev_2255| (|get.::.1_2251| x_48))
                                                                                                                                                  (|::_3| (|get.::.0_2250| x_48) |[]_…
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (|List.length_2252| (|get.::.1_2251| x_48))
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48)))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (|List.append_2259|
                                                                                                                                                        (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48)))
                                                                                                                                                        (|::_3| (|get.::.…
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (is_sorted_41 (|get.::.1_2251| (|List.rev_2255| x_48)))
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (|List.length_2252| (|get.::.1_2251| (|get.::.1_2251| x_48)))
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (is_sorted_41 (|get.::.1_2251| x_48))
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (|List.append_2259|
                                                                                                                                                                (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| x_48)))
                                                                                                                                                                (|::_3| (|get.::.…
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (let ((a!1 (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                        (a!2 …
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (|List.length_2252| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (is_sorted_41 (|get.::.1_2251| (|get.::.1_2251| x_48)))
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (let ((a!1 (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                          (|List.a…
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| x_48))))))
                                                                                                                                                                            (|List.a…
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (is_sorted_41 (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| x_48))))
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                (|List.r…
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                    (|List.l…
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (is_sorted_41 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (let ((a!1 (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                            (a!2 …
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                          (|List.a…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                            (|List.r…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                              (|List.a…
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                (|List.l…
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                  (|List.a…
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                    (is_sort…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                                          (a!2 …
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                                            (a!2 …
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                          (|List.a…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| x_48))))))
                                                                                                                                                                                                            (is_sort…
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                              (|List.a…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                                (|List.r…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2251| (|List.rev_2255| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                                      (|List.a…
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48)))))
                                                                                                                                                                                                                            (a!2 …
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                                          (|List.a…
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| x_48))))))
                                                                                                                                                                                                                            (|List.l…
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2251| (|get.::.1_2251| (|get.::.1_2251| (|List.rev_2255| x_48))))))
                                                                                                                                                                                                                              (is_sort…
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • Sat (Some let (x : int list) = [1733; 1733; 1733; 1733; 1733] )

                                                                                                                                                                                                                            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
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds x)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds x)))
                                                                                                                                                                                                                            • is_sorted (List.tl (List.tl (merge_sort x)))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • odds (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 (List.tl (odds 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 …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds x))
                                                                                                                                                                                                                            • odds (odds (odds (odds …)))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (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 x)))))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                            • is_sorted (merge_sort x)
                                                                                                                                                                                                                            • odds (odds (odds x))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                            • is_sorted (List.tl (List.tl (List.tl (merge_sort x))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • odds (List.tl x)
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                            • is_sorted (List.tl (merge_sort x))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                            • odds x
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds x)))
                                                                                                                                                                                                                            • merge_sort (odds (odds x))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds x)
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            • odds (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 …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl x))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds x)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge_sort x
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds x))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds x)
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl x)))
                                                                                                                                                                                                                            • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                            • odds (odds (List.tl x))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            blocked
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (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 (odds (odds (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) else if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (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 (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                            • is_sorted (List.tl (List.tl (List.tl (List.tl (merge_sort x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (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 (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (odds (odds (odds …)))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (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 …))))
                                                                                                                                                                                                                            • odds (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 (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))))) then if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then … else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) else (List.tl (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then … else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))))))) (if List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))))) then List.tl (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else …) else if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else …)
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) else if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • odds (odds (odds (odds …)))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (List.tl (odds …))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (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 …))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (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 …))))))
                                                                                                                                                                                                                            • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                            • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                            • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (odds (List.tl (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 …))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                            proof attempt
                                                                                                                                                                                                                            ground_instances100
                                                                                                                                                                                                                            definitions0
                                                                                                                                                                                                                            inductions0
                                                                                                                                                                                                                            search_time
                                                                                                                                                                                                                            3.744s
                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                            • start[3.744s] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (merge_sort_37 x_50)
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (is_sorted_41 (merge_sort_37 x_50))
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (odds_2011 (|get.::.1_2010| x_50))
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (merge_sort_37 (odds_2011 (|get.::.1_2010| x_50)))
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (odds_2011 x_50)
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (merge_sort_37 (odds_2011 x_50))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (merge_14 (merge_sort_37 (odds_2011 x_50))
                                                                                                                                                                                                                                                    (merge_sort_37 (odds_2011 (|get.::.1_2010| x_50…
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (odds_2011 (|get.::.1_2010| (|get.::.1_2010| x_50)))
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (odds_2011 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| x_50))))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (is_sorted_41 (|get.::.1_2010| (merge_sort_37 x_50)))
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                      (merge_sort_37 a!1))
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (odds_2011 (odds_2011 (|get.::.1_2010| x_50)))
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (let ((a!1 (merge_sort_37 (odds_2011 (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                              (a!2 (odds_2011 (|g…
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (merge_sort_37 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_2009| (merge_sort_37 (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                  (a!4 (|get.::…
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (odds_2011 (|get.::.1_2010| (odds_2011 x_50)))
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (merge_sort_37 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (odds_2011 (odds_2011 x_50))
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (merge_sort_37 (odds_2011 (odds_2011 x_50)))
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (let ((a!1 (merge_sort_37 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                        (merge_14 (merge_sort_…
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                          (odds_2011 a!1…
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                            (odds_20…
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_2009| (merge_sort_37 (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                                  (a!3 (|get.::…
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                (odds_20…
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (odds_2011 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 x_50))))
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                                        (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                      (odds_2011 a!1…
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                        (odds_2011 a!1))
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (is_sorted_41 (|get.::.1_2010| (|get.::.1_2010| (merge_sort_37 x_50))))
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                            (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.1_2010| (…
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                    (odds_2011 (|g…
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                        (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (odds_2011 (odds_2011 (odds_2011 x_50)))
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds_2011 (odds_2011 (odds_2011 x_50))))
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                              (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (let ((a!1 (merge_sort_37 (odds_2011 (odds_2011 (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                    (a!2 (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (merge_sort_37 (odds_2011 (|get.::.1_2010| (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.0_200…
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                    (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                        (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                              (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                  (merge_14 (merge_sor…
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                                                                                        (a!2 (|get.::.1_2010| (…
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.0_2009| (merge_sort_37 (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                                                                                          (a!3 (|get.::…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (merge_sort_37 x_50))))))
                                                                                                                                                                                                                                                                                                                                        (is_sorted…
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                          (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                            (odds_2011 (|g…
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                              (odds_2011 (|get.::.1_2010…
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                  (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                    (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                      (odds_20…
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                        (odds_2011 (|g…
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                          (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                            (odds_20…
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                              (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50)))))
                                                                                                                                                                                                                                                                                                                                                                    (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (odds_2011 (odds_2011 (odds_2011 (odds_2011 x_50))))
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                            (a!2 (|get.::.1_2010| (odds_2…
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                          (odds_2011 (|g…
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                (a!2 (merge_sort_37 (od…
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                              (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                (odds_2011 (|get.::.1_2010…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                    (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                      (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                          (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (merge_sort_37 (odds_2011 (|get.::.1_2010| (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                                (a!2 (|get.::.0_200…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                        (odds_2011 (odds_201…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2011 (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                            (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2011 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                              (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2010| (|get.::.1_2010| (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (odds_2011 (|g…
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2011 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (odds_2011 (odds_201…
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (odds_2011 (|get.::.1_2010…
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2010| (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds_2011 …
                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_2011 (odds_2011 (odds_2011 (|get.::.1_2010| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2011 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2010| (odds_2011 (|get.::.1_2010| (odds_2011 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                          (a!2 (odds_2011 (…
                                                                                                                                                                                                                                                                                                                                                                                                                                    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.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                            && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. not (x <> [] && List.tl 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:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (x <> [] && List.tl 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':
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    We can eliminate destructors by the following substitution:
                                                                                                                                                                                                                                                                                                                                                                                                                                     x -> x1 :: x2
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1'':
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted (merge_sort (odds x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted (merge_sort (odds (x1 :: x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge (merge_sort (odds (x1 :: x2))) (merge_sort (odds x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Candidates for generalization:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     odds (x1 :: x2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     odds x2
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1''':
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted (merge_sort gen_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted (merge_sort gen_1)
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge (merge_sort gen_1) (merge_sort gen_2))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Candidates for generalization:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     merge_sort gen_1
                                                                                                                                                                                                                                                                                                                                                                                                                                     merge_sort gen_2
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1'''':
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted gen_3
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge gen_3 gen_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     Aborting proof attempt for merge_sort_sorts.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:induct merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Checkpoints:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted gen_3
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge gen_3 gen_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Error[/server]: 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.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    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 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (y = []) && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (y = []) && List.hd x < List.hd y && φ (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> φ x y).
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 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 definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 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 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H6. (List.tl y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H7. List.hd y <= List.hd (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H8. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 2.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H6. List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 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 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. List.hd x <= List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H6. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H7. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 1.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances6
                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions21
                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                    1.081s
                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert lower11
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith pivots7
                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count126601
                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause123
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check24
                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var155
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert upper16
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits11
                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions90
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith add rows18
                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations213
                                                                                                                                                                                                                                                                                                                                                                                                                                    interface eqs1
                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts17
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith fixed eqs3
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                    minimized lits6
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert diseq2
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax15
                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks9
                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs306
                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause83
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter7
                                                                                                                                                                                                                                                                                                                                                                                                                                    memory107.050000
                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory123.840000
                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs56925002017.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.081s, "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.081s, "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 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (y = []) && List.hd x < List.hd y && φ (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                      • 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 && is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                && ((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                     (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not (is_sorted x && 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) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                         || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (is_sorted x && 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                             (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
                                                                                                                                                                                                                                                                                                                                                                                                                                                             (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 (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.074s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || 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
                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (List.hd x <= List.hd (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.hd x <= List.hd (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             && ((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || List.hd x <= List.hd (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            && (((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || is_sorted (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (List.hd x <= List.hd (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                            [merge, is_sorted, is_sorted, merge, is_sorted, is_sorted, is_sorted, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((((x = [] || y = []) || not (List.hd y <= List.hd x)) || 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.074s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                ((((((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.tl y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (List.hd y <= List.hd (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || List.hd y <= List.hd (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && ((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.hd y <= List.hd (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                && (((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || is_sorted (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (List.hd y <= List.hd (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                [merge, is_sorted, is_sorted, merge, is_sorted, is_sorted, is_sorted, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • 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.074s, "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
                                                                                                                                                                                                                                                                                                                                                                                                                                                    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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. not (x <> [] && List.tl 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:
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not (x <> [] && List.tl 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':
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. is_sorted (merge_sort (odds 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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                 Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:def merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:rw merge_sorts)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:induct merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                definitions7
                                                                                                                                                                                                                                                                                                                                                                                                                                                inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                0.674s
                                                                                                                                                                                                                                                                                                                                                                                                                                                Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[0.674s, "Goal"] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                  is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.674s, "1"] is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • Split ((not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                           && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                               (((not (x = []) && not (x <> [] && List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && is_sorted (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && is_sorted (merge_sort (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                           :cases [not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((x = [] || x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((x = [] || x <> [] && List.tl x = []) || not (is_sorted (merge_sort (odds (List.tl x))))) || not (is_sorted (merge_sort (odds x)))) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.673s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((x = [] || x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                        merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                            into
                                                                                                                                                                                                                                                                                                                                                                                                                                                            true
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            []
                                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                            merge_sorts
                                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                            not (x <> [] && List.tl x = []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[0.673s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                not (x <> [] && List.tl 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 -> int = <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.015s
                                                                                                                                                                                                                                                                                                                                                                                                                                                          details
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert lower8
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith pivots5
                                                                                                                                                                                                                                                                                                                                                                                                                                                          rlimit count4980
                                                                                                                                                                                                                                                                                                                                                                                                                                                          mk clause28
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype occurs check29
                                                                                                                                                                                                                                                                                                                                                                                                                                                          mk bool var88
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert upper11
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                          decisions23
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith add rows11
                                                                                                                                                                                                                                                                                                                                                                                                                                                          propagations45
                                                                                                                                                                                                                                                                                                                                                                                                                                                          conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith fixed eqs8
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype constructor ax12
                                                                                                                                                                                                                                                                                                                                                                                                                                                          final checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                          added eqs70
                                                                                                                                                                                                                                                                                                                                                                                                                                                          del clause6
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith eq adapter8
                                                                                                                                                                                                                                                                                                                                                                                                                                                          memory61.990000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          max memory123.840000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num allocs68918816222.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[0.015s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                              (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.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (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.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                               (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            []
                                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_4085|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (|count_`ty_0 list`_4085| (|get.::.1_4063| y_4073))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|count_`ty_0 list`_4085| y_4073)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (th-lemma (or (= y_4073 |[]_2|)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (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.012s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert lower5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith pivots4
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count2404
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check26
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var62
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert upper7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions19
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith add rows7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations33
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts9
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith fixed eqs4
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs41
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause5
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    memory61.910000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory123.840000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs68335260567.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.012s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        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.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (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.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_4085|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|count_`ty_0 list`_4085| (|get.::.1_4063| y_4073))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (|count_`ty_0 list`_4085| y_4073)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (= (|count_`ty_0 list`_4085| y_4073)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (+ 1 (|count_`ty_0 list`_4085| (|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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              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 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (y = []) && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (y = []) && List.hd x < List.hd y && φ a (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ a x y).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definition of merge to the following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 3.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               C1. 0 = num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 3.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H2. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               0 = num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 3.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               0 = num_occurs a x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 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:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              definitions10
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              0.155s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.155s, "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.155s, "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 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (y = []) && List.hd x < List.hd y && φ a (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • 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.152s, "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.152s, "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.152s, "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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ((((not (y = []) || List.hd y <= List.hd x) || 0 = num_occurs a y) || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (((not (y = []) || not (List.hd y <= List.hd x)) || 0 = num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && (0 = num_occurs a x || not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              merge
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          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 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          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 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. 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. 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. (List.tl 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.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. (List.tl 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 definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:def odds)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:induct num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          definitions26
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          0.480s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[0.480s, "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[0.480s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • induction on (functional num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              :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)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Split ((((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (not (x <> [] && List.hd x = a) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (not (x = []) && not (List.tl x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs a x + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && ((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ((not (x = []) && not (x <> [] && List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (not (x = []) && not (List.tl x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a x + -1 * num_occurs a (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && ((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((not (x = []) && x <> []) && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && (not (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (not (x = []) && not (List.tl x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs a x + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     :cases [((((x <> [] && List.hd x = a) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ((((x = [] || x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (((((x = [] || not (x <> [])) || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x + -1 * num_occurs a (odds x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((((x = [] || not (x <> [])) || not (List.hd x = a)) || not (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)))) || x = []) || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[0.479s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((((x = [] || not (x <> [])) || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ((((((x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || List.hd (List.tl x) = List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.tl 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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (((((x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (List.hd (List.tl x) = List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || List.tl 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)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (((x = [] || not (List.tl (List.tl x) = [])) || List.tl 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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  [num_occurs, num_occurs, odds, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ((((x = [] || x <> [] && List.hd x = a) || not (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)))) || x = []) || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.479s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((((x = [] || x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((((((x = [] || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || List.hd (List.tl x) = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           + -1 * num_occurs a (odds (List.tl (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && ((((((x = [] || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (List.hd (List.tl x) = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              + -1 * num_occurs a (odds (List.tl (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && ((((x = [] || List.hd x = a) || not (List.tl (List.tl x) = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             + -1 * num_occurs a (odds (List.tl (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [num_occurs, num_occurs, odds, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((((x <> [] && List.hd x = a) && not (x = []) || not (x <> [] && List.hd x = a) && not (x = [])) || x = []) || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[0.479s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((x <> [] && List.hd x = a) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && φ a (odds (List.tl x)) && φ a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. not (x <> [] && List.tl 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:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. not (x <> [] && List.tl 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.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H2. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H3. num_occurs a (odds x) = num_occurs a (merge_sort (odds 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:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H2. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           -1 + num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H3. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H4. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (:def merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (:rw num_occur_merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (:rw num_occurs_arith)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (:induct merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      definitions15
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      6.952s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[6.952s, "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[6.952s, "1"] num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && φ a (odds (List.tl x)) && φ a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • Split ((not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || num_occurs a x = num_occurs a (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (((not (x = []) && not (x <> [] && List.tl 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 (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a x = num_occurs a (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (((x = [] || x <> [] && List.tl 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 = [] || x <> [] && List.tl 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[6.952s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((x = [] || x <> [] && List.tl 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((((x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (num_occurs a (List.tl x) + -1 * num_occurs a (odds 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 (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && (((((x = [] || List.tl 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 (num_occurs a (odds x) = num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      -1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      + num_occurs a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [num_occurs, num_occurs, merge_sort, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • num_occurs_arith
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • num_occurs_arith
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              not (x <> [] && List.tl x = []) && not (x = []) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[6.952s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  not (x <> [] && List.tl 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, 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)!