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.046s
details
Expand
smt_stats
arith offset eqs36
num checks18
arith assert lower156
arith pivots81
rlimit count65711
mk clause243
datatype occurs check307
mk bool var674
arith assert upper166
datatype splits58
decisions398
arith add rows292
arith bound prop6
propagations600
interface eqs9
conflicts42
arith fixed eqs109
datatype accessor ax70
minimized lits2
arith conflicts7
arith assert diseq29
datatype constructor ax84
num allocs1332881335
final checks37
added eqs943
del clause138
arith eq adapter117
memory25.790000
max memory26.990000
Expand
  • start[0.046s]
      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 … 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_139|
          (|Ordinal.Int_105| (|count_`int list`_1491| l_1478))
          (|Ordinal.Int_105| 1))
        expansions
        • unroll
          expr
          (|Ordinal.plus_125|
            (|Ordinal.shift_139|
              (|Ordinal.Int_105| (|count_`int list`_1491| l_1478))
          …
          expansions
          • unroll
            expr
            (|Ordinal.shift_139|
              (|Ordinal.Int_105| (|count_`int list`_1491| (|get.::.1_1477| l_1478)))
              (|Or…
            expansions
            • unroll
              expr
              (let ((a!1 (|Ordinal.shift_139|
                           (|Ordinal.Int_105|
                             (|count_`int list`_14…
              expansions
              • unroll
                expr
                (let ((a!1 (|Ordinal.shift_139|
                             (|Ordinal.Int_105|
                               (|count_`int list`_14…
                expansions
                • unroll
                  expr
                  (|count_`int list`_1491| (|get.::.1_1477| l_1478))
                  expansions
                  • unroll
                    expr
                    (|count_`int list`_1491| m_1479)
                    expansions
                    • unroll
                      expr
                      (|count_`int list`_1491| l_1478)
                      expansions
                      • unsat
                        (let ((a!1 (|get.Ordinal.Cons.1_1483|
                                     (|Ordinal.shift_139|
                                       (|Ordinal.Int…

                      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.078s
                      details
                      Expand
                      smt_stats
                      arith offset eqs59
                      num checks34
                      arith assert lower427
                      arith pivots192
                      rlimit count45418
                      mk clause639
                      datatype occurs check641
                      mk bool var1741
                      arith assert upper415
                      datatype splits114
                      decisions1253
                      arith add rows557
                      arith bound prop19
                      propagations1628
                      interface eqs9
                      conflicts66
                      arith fixed eqs274
                      datatype accessor ax224
                      minimized lits5
                      arith conflicts9
                      arith assert diseq30
                      datatype constructor ax264
                      num allocs1291256662
                      final checks54
                      added eqs2382
                      del clause291
                      arith eq adapter347
                      memory22.340000
                      max memory26.990000
                      Expand
                      • start[0.078s]
                          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 … 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_125|
                              (|Ordinal.shift_139|
                                (|Ordinal.Int_105| (|count_`int list`_1491| l_1478))
                            …
                            expansions
                            • unroll
                              expr
                              (|Ordinal.shift_139|
                                (|Ordinal.Int_105| (|count_`int list`_1491| l_1478))
                                (|Ordinal.Int_105| 1))
                              expansions
                              • unroll
                                expr
                                (|Ordinal.plus_125|
                                  (|Ordinal.shift_139|
                                    (|Ordinal.Int_105| (|count_`int list`_1491| l_1478))
                                …
                                expansions
                                • unroll
                                  expr
                                  (let ((a!1 (|Ordinal.plus_125|
                                               (|Ordinal.shift_139|
                                                 (|Ordinal.Int_105| (…
                                  expansions
                                  • unroll
                                    expr
                                    (|count_`int list`_1491| (|get.::.1_1477| m_1479))
                                    expansions
                                    • unroll
                                      expr
                                      (|count_`int list`_1491| m_1479)
                                      expansions
                                      • unroll
                                        expr
                                        (|count_`int list`_1491| l_1478)
                                        expansions
                                        • unroll
                                          expr
                                          (|count_`int list`_1491| (|get.::.1_1477| l_1478))
                                          expansions
                                          • unroll
                                            expr
                                            (|count_`int list`_1491| (|get.::.1_1477| (|get.::.1_1477| m_1479)))
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|get.Ordinal.Cons.2_1484|
                                                           (|Ordinal.shift_139|
                                                             (|Ordinal.Int…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|get.Ordinal.Cons.0_1482|
                                                             (|Ordinal.shift_139|
                                                               (|Ordinal.Int…
                                                expansions
                                                • unroll
                                                  expr
                                                  (let ((a!1 (|get.Ordinal.Cons.2_1484|
                                                               (|Ordinal.shift_139|
                                                                 (|Ordinal.Int…
                                                  expansions
                                                  • unroll
                                                    expr
                                                    (let ((a!1 (|get.Ordinal.Cons.0_1482|
                                                                 (|Ordinal.shift_139|
                                                                   (|Ordinal.Int…
                                                    expansions
                                                    • unroll
                                                      expr
                                                      (let ((a!1 (|Ordinal.plus_125|
                                                                   (|Ordinal.shift_139|
                                                                     (|Ordinal.Int_105| (…
                                                      expansions
                                                      • unroll
                                                        expr
                                                        (|Ordinal.shift_139|
                                                          (|get.Ordinal.Cons.2_1484|
                                                            (|Ordinal.Int_105| (|count_`int list`_1491| l_…
                                                        expansions
                                                        • unroll
                                                          expr
                                                          (let ((a!1 (|Ordinal.plus_125|
                                                                       (|Ordinal.shift_139|
                                                                         (|Ordinal.Int_105| (…
                                                          expansions
                                                          • unsat
                                                            (let ((a!1 (>= (ite (>= (|get.::.0_1476| m_1479) 0) (|get.::.0_1476| m_1479) 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 (List.tl l = [] && l <> []) && not (l = [])]
                                                          proof
                                                          detailed proof
                                                          ground_instances6
                                                          definitions0
                                                          inductions0
                                                          search_time
                                                          0.044s
                                                          details
                                                          Expand
                                                          smt_stats
                                                          arith offset eqs4
                                                          num checks14
                                                          arith assert lower27
                                                          arith pivots16
                                                          rlimit count5180
                                                          mk clause72
                                                          datatype occurs check28
                                                          mk bool var160
                                                          arith assert upper26
                                                          datatype splits3
                                                          decisions44
                                                          arith add rows37
                                                          arith bound prop5
                                                          propagations44
                                                          interface eqs1
                                                          conflicts18
                                                          arith fixed eqs23
                                                          datatype accessor ax9
                                                          minimized lits1
                                                          arith conflicts3
                                                          arith assert diseq3
                                                          datatype constructor ax19
                                                          num allocs1420800959
                                                          final checks9
                                                          added eqs105
                                                          del clause20
                                                          arith eq adapter20
                                                          memory27.030000
                                                          max memory27.030000
                                                          Expand
                                                          • start[0.044s]
                                                              not (List.tl l = [] && l <> [])
                                                              && not (l = [])
                                                                 && Ordinal.count l >= 0 && Ordinal.count (List.tl (List.tl l)) >= 0
                                                              ==> not
                                                                  (not
                                                                   (List.tl (List.tl (List.tl l)) = [] && (List.tl (List.tl l)) <> [])
                                                                   && not (List.tl (List.tl l) = []))
                                                                  || Ordinal.<< (Ordinal.Int (Ordinal.count (List.tl (List.tl l))))
                                                                     (Ordinal.Int (Ordinal.count l))
                                                          • simplify
                                                            into
                                                            (not
                                                             (((not (List.tl l = [] && l <> []) && not (l = [])) && Ordinal.count l >= 0)
                                                              && Ordinal.count (List.tl (List.tl l)) >= 0)
                                                             || not
                                                                (not (List.tl (List.tl (List.tl l)) = [] && (List.tl (List.tl l)) <> [])
                                                                 && not (List.tl (List.tl l) = [])))
                                                            || Ordinal.<< (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_105|
                                                                             (|count_`ty_0 list`_1529|
                                                                               (|get.::.1_1513|…
                                                                expansions
                                                                • unroll
                                                                  expr
                                                                  (|count_`ty_0 list`_1529| (|get.::.1_1513| (|get.::.1_1513| l_1520)))
                                                                  expansions
                                                                  • unroll
                                                                    expr
                                                                    (|count_`ty_0 list`_1529| l_1520)
                                                                    expansions
                                                                    • unroll
                                                                      expr
                                                                      (|count_`ty_0 list`_1529|
                                                                        (|get.::.1_1513| (|get.::.1_1513| (|get.::.1_1513| l_1520))))
                                                                      expansions
                                                                      • unroll
                                                                        expr
                                                                        (let ((a!1 (|Ordinal.Int_105|
                                                                                     (|count_`ty_0 list`_1529|
                                                                                       (|get.::.1_1513|…
                                                                        expansions
                                                                        • unroll
                                                                          expr
                                                                          (|count_`ty_0 list`_1529| (|get.::.1_1513| l_1520))
                                                                          expansions
                                                                          • unsat
                                                                            (let ((a!1 (ite (>= (|count_`ty_0 list`_1529| (|get.::.1_1513| l_1520)) 0)
                                                                                            (|count_`…

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

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

                                                                          Defining Merge Sort

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

                                                                          In [8]:
                                                                          let rec merge_sort l =
                                                                           match l with
                                                                            | []  -> []
                                                                            | [_] -> l
                                                                            | _ :: ls -> merge (merge_sort (odds l)) (merge_sort (odds ls))
                                                                          
                                                                          Out[8]:
                                                                          val merge_sort : int list -> int list = <fun>
                                                                          File "jupyter cell 8", line 1, characters 0-129:
                                                                          Error: rejected definition for function merge_sort,
                                                                          Imandra could not prove termination. 
                                                                          hint: problematic sub-call from `merge_sort l`
                                                                          to `merge_sort (odds (List.tl l))`  under path
                                                                          not (List.tl l = [] && l <> []) and not (l = [])
                                                                          could not be proved to decrease (measured subset: (l))
                                                                          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.
                                                                          
                                                                          Subgoal 1:
                                                                          
                                                                           H0. not (x = [])
                                                                           H1. not (List.tl x = [])
                                                                           H2. List.length x <= List.length (odds x)
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          This simplifies, using the definition of List.length to:
                                                                          
                                                                          Subgoal 1':
                                                                          
                                                                           H0. x <> []
                                                                           H1. (List.tl x) <> []
                                                                           H2. List.length (List.tl x) <= (-1 + List.length (odds x))
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          
                                                                          We can eliminate destructors by the following substitution:
                                                                           x -> x1 :: x2
                                                                          
                                                                          This produces the modified subgoal:
                                                                          
                                                                          Subgoal 1'':
                                                                          
                                                                           H0. x2 <> []
                                                                           H1. List.length x2 <= (-1 + List.length (odds (x1 :: x2)))
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          
                                                                          Must try induction.
                                                                          
                                                                          Note: We must proceed by induction, but our current subgoal is less
                                                                          appropriate for induction than our original conjecture. Thus, we prefer to
                                                                          abandon our work until now and return our focus to the original conjecture
                                                                          which we shall attempt to prove by induction directly.
                                                                          
                                                                          We shall induct according to a scheme derived from odds.
                                                                          
                                                                          Induction scheme:
                                                                          
                                                                           (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                           && (not (x = [])
                                                                               && not (List.tl x = [] && x <> []) && φ (List.tl (List.tl x)) ==> 
                                                                               φ x).
                                                                          
                                                                          2 nontautological subgoals.
                                                                          
                                                                          Subgoal 2:
                                                                          
                                                                           H0. not (x = [])
                                                                           H1. not (List.tl x = [])
                                                                           H2. List.length x <= List.length (odds x)
                                                                          |---------------------------------------------------------------------------
                                                                           not (List.tl x = [] && x <> []) && not (x = [])
                                                                          
                                                                          But simplification reduces this to true, using the forward-chaining rule
                                                                          List.len_nonnegative.
                                                                          
                                                                          Subgoal 1:
                                                                          
                                                                           H0. not (x = [])
                                                                           H1. not (List.tl x = [] && x <> [])
                                                                           H2. not
                                                                               (not (List.tl (List.tl x) = [])
                                                                                && not (List.tl (List.tl (List.tl x)) = []))
                                                                               || not
                                                                                  (List.length (List.tl (List.tl x)) <=
                                                                                   List.length (odds (List.tl (List.tl x))))
                                                                           H3. not (x = [])
                                                                           H4. not (List.tl x = [])
                                                                           H5. List.length x <= List.length (odds x)
                                                                          |---------------------------------------------------------------------------
                                                                           false
                                                                          
                                                                          This simplifies, using the definitions of List.length and odds to the
                                                                          following 3 subgoals:
                                                                          
                                                                          Subgoal 1.3:
                                                                          
                                                                           H0. 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.
                                                                          
                                                                          
                                                                          Proved
                                                                          proof
                                                                          ground_instances0
                                                                          definitions14
                                                                          inductions1
                                                                          search_time
                                                                          1.429s
                                                                          Expand
                                                                          • start[1.429s, "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[1.429s, "1"]
                                                                                (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                            • simplify
                                                                              into
                                                                              (x = [] || List.tl x = [])
                                                                              || not (List.length (List.tl x) <= (-1 + List.length (odds x)))
                                                                              expansions
                                                                              List.length
                                                                              rewrite_steps
                                                                                forward_chaining
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative
                                                                              • Elim_destructor (:cstor :: :replace x1 :: x2 :context [])
                                                                              • induction on (functional odds)
                                                                                :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                        && (not (x = [])
                                                                                            && not (List.tl x = [] && x <> []) && φ (List.tl (List.tl x))
                                                                                            ==> φ x)
                                                                              • Split (((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                         || not (not (x = []) && not (List.tl x = [])))
                                                                                        || not (List.length x <= List.length (odds x)))
                                                                                       && ((not
                                                                                            ((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                             && (not
                                                                                                 (not (List.tl (List.tl x) = [])
                                                                                                  && not (List.tl (List.tl (List.tl x)) = []))
                                                                                                 || not
                                                                                                    (List.length (List.tl (List.tl x)) <=
                                                                                                     List.length (odds (List.tl (List.tl x))))))
                                                                                            || not (not (x = []) && not (List.tl x = [])))
                                                                                           || not (List.length x <= List.length (odds x)))
                                                                                       :cases [((x = [] || List.tl x = [])
                                                                                                || not (List.length x <= List.length (odds x)))
                                                                                               || not (List.tl x = [] && x <> []) && not (x = []);
                                                                                               (((x = [] || List.tl x = [] && x <> [])
                                                                                                 || not
                                                                                                    (not
                                                                                                     (not (List.tl (List.tl x) = [])
                                                                                                      && not (List.tl (List.tl (List.tl x)) = []))
                                                                                                     || not
                                                                                                        (List.length (List.tl (List.tl x)) <=
                                                                                                         List.length (odds (List.tl (List.tl x))))))
                                                                                                || List.tl x = [])
                                                                                               || not (List.length x <= List.length (odds x))])
                                                                                • subproof
                                                                                  (((x = [] || List.tl x = [] && x <> []) || not (not (not (List.tl (List.tl x) = []) && not (List.tl (List.tl (List.tl x)) = [])) || not (List.length (List.tl (List.tl x)) <= List.length (odds (List.tl (List.tl x)))))) || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                                  • start[0.927s, "1"]
                                                                                      (((x = [] || List.tl x = [] && x <> [])
                                                                                        || not
                                                                                           (not
                                                                                            (not (List.tl (List.tl x) = [])
                                                                                             && not (List.tl (List.tl (List.tl x)) = []))
                                                                                            || not
                                                                                               (List.length (List.tl (List.tl x)) <=
                                                                                                List.length (odds (List.tl (List.tl x))))))
                                                                                       || List.tl x = [])
                                                                                      || not (List.length x <= List.length (odds x))
                                                                                  • simplify
                                                                                    into
                                                                                    ((((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 (List.tl x = [] && x <> []) && not (x = [])
                                                                                    • start[0.927s, "2"]
                                                                                        ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x)))
                                                                                        || not (List.tl x = [] && x <> []) && not (x = [])
                                                                                    • simplify
                                                                                      into
                                                                                      true
                                                                                      expansions
                                                                                      []
                                                                                      rewrite_steps
                                                                                        forward_chaining
                                                                                        • List.len_nonnegative
                                                                                        • List.len_nonnegative

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

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

                                                                                Termination proof

                                                                                call `merge_sort (odds l)` from `merge_sort l`
                                                                                originalmerge_sort l
                                                                                submerge_sort (odds l)
                                                                                original ordinalmerge_sort_measure l
                                                                                sub ordinalmerge_sort_measure (odds l)
                                                                                path[not (List.tl l = [] && l <> []) && not (l = [])]
                                                                                proof
                                                                                detailed proof
                                                                                ground_instances1
                                                                                definitions0
                                                                                inductions0
                                                                                search_time
                                                                                0.024s
                                                                                details
                                                                                Expand
                                                                                smt_stats
                                                                                num checks3
                                                                                arith assert lower6
                                                                                arith pivots1
                                                                                rlimit count4870
                                                                                mk clause3
                                                                                datatype occurs check15
                                                                                mk bool var46
                                                                                datatype splits4
                                                                                decisions11
                                                                                propagations4
                                                                                conflicts8
                                                                                datatype accessor ax7
                                                                                datatype constructor ax12
                                                                                final checks3
                                                                                added eqs39
                                                                                del clause3
                                                                                memory53.070000
                                                                                max memory67.580000
                                                                                num allocs8896047608.000000
                                                                                Expand
                                                                                • start[0.024s]
                                                                                    not (List.tl l = [] && l <> [])
                                                                                    && not (l = [])
                                                                                       && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                          && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >=
                                                                                             0
                                                                                    ==> not
                                                                                        (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = []))
                                                                                        && not
                                                                                           (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = []))
                                                                                        || Ordinal.<<
                                                                                           (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 (List.tl l = [] && l <> []) && not (l = []))
                                                                                     && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                                    && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >= 0)
                                                                                   || not (not (List.tl (odds l) = [] && (odds l) <> []) && not (odds l = [])))
                                                                                  || Ordinal.<<
                                                                                     (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_1843| (odds_1847 l_1853)) 0)
                                                                                                      (|List.length_1843| (…
                                                                                      expansions
                                                                                      • unsat
                                                                                        (let ((a!1 (and (not (= l_1853 |[]_2|))
                                                                                                        (not (= (|get.::.1_1836| l_1853) |[]_2|))))
                                                                                        …

                                                                                      call `merge_sort (odds (List.tl l))` from `merge_sort l`
                                                                                      originalmerge_sort l
                                                                                      submerge_sort (odds (List.tl l))
                                                                                      original ordinalmerge_sort_measure l
                                                                                      sub ordinalmerge_sort_measure (odds (List.tl l))
                                                                                      path[not (List.tl l = [] && l <> []) && not (l = [])]
                                                                                      proof
                                                                                      detailed proof
                                                                                      ground_instances4
                                                                                      definitions0
                                                                                      inductions0
                                                                                      search_time
                                                                                      0.043s
                                                                                      details
                                                                                      Expand
                                                                                      smt_stats
                                                                                      num checks10
                                                                                      arith assert lower6
                                                                                      arith pivots6
                                                                                      rlimit count3244
                                                                                      mk clause16
                                                                                      datatype occurs check67
                                                                                      mk bool var117
                                                                                      arith assert upper14
                                                                                      datatype splits18
                                                                                      decisions32
                                                                                      arith add rows8
                                                                                      propagations34
                                                                                      conflicts15
                                                                                      datatype accessor ax13
                                                                                      arith conflicts1
                                                                                      datatype constructor ax25
                                                                                      final checks15
                                                                                      added eqs102
                                                                                      del clause8
                                                                                      arith eq adapter2
                                                                                      memory53.040000
                                                                                      max memory67.580000
                                                                                      num allocs8696430133.000000
                                                                                      Expand
                                                                                      • start[0.043s]
                                                                                          not (List.tl l = [] && l <> [])
                                                                                          && not (l = [])
                                                                                             && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                                && (if List.length (odds (List.tl l)) >= 0
                                                                                                    then List.length (odds (List.tl l)) else 0)
                                                                                                   >= 0
                                                                                          ==> not
                                                                                              (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                               && not (odds (List.tl l) = []))
                                                                                              && not
                                                                                                 (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                                  && not (odds (List.tl l) = []))
                                                                                              || Ordinal.<<
                                                                                                 (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 (List.tl l = [] && l <> []) && not (l = []))
                                                                                           && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                                          && (if List.length (odds (List.tl l)) >= 0
                                                                                              then List.length (odds (List.tl l)) else 0)
                                                                                             >= 0)
                                                                                         || not
                                                                                            (not (List.tl (odds (List.tl l)) = [] && (odds (List.tl l)) <> [])
                                                                                             && not (odds (List.tl l) = [])))
                                                                                        || Ordinal.<<
                                                                                           (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_1843| (odds_1847 (|get.::.1_1836| l_1853))) 0))
                                                                                                  (a!3 (|Ordinal.In…
                                                                                            expansions
                                                                                            • unroll
                                                                                              expr
                                                                                              (odds_1847 (|get.::.1_1836| l_1853))
                                                                                              expansions
                                                                                              • unroll
                                                                                                expr
                                                                                                (|List.length_1843| (odds_1847 (|get.::.1_1836| l_1853)))
                                                                                                expansions
                                                                                                • unroll
                                                                                                  expr
                                                                                                  (|List.length_1843| l_1853)
                                                                                                  expansions
                                                                                                  • unsat
                                                                                                    (let ((a!1 (= (|get.::.1_1836| (odds_1847 (|get.::.1_1836| l_1853))) |[]_2|))
                                                                                                          (a!3 (not ((_ is…

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

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

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

                                                                                                  Proving Merge Sort correct

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

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

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

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

                                                                                                  Termination proof

                                                                                                  call `is_sorted (List.tl x)` from `is_sorted x`
                                                                                                  originalis_sorted x
                                                                                                  subis_sorted (List.tl x)
                                                                                                  original ordinalOrdinal.Int (Ordinal.count x)
                                                                                                  sub ordinalOrdinal.Int (Ordinal.count (List.tl x))
                                                                                                  path[List.hd x <= List.hd (List.tl x) && not (List.tl x = [] && x <> []) && not (x = [])]
                                                                                                  proof
                                                                                                  detailed proof
                                                                                                  ground_instances3
                                                                                                  definitions0
                                                                                                  inductions0
                                                                                                  search_time
                                                                                                  0.048s
                                                                                                  details
                                                                                                  Expand
                                                                                                  smt_stats
                                                                                                  num checks8
                                                                                                  arith assert lower30
                                                                                                  arith pivots9
                                                                                                  rlimit count2914
                                                                                                  mk clause32
                                                                                                  datatype occurs check24
                                                                                                  mk bool var108
                                                                                                  arith assert upper19
                                                                                                  datatype splits5
                                                                                                  decisions22
                                                                                                  arith add rows18
                                                                                                  arith bound prop1
                                                                                                  propagations31
                                                                                                  interface eqs2
                                                                                                  conflicts12
                                                                                                  arith fixed eqs13
                                                                                                  datatype accessor ax6
                                                                                                  arith conflicts2
                                                                                                  arith assert diseq2
                                                                                                  datatype constructor ax10
                                                                                                  final checks9
                                                                                                  added eqs72
                                                                                                  del clause17
                                                                                                  arith eq adapter19
                                                                                                  memory56.720000
                                                                                                  max memory67.580000
                                                                                                  num allocs9036365028.000000
                                                                                                  Expand
                                                                                                  • start[0.048s]
                                                                                                      List.hd x <= List.hd (List.tl x)
                                                                                                      && not (List.tl x = [] && x <> [])
                                                                                                         && not (x = [])
                                                                                                            && Ordinal.count x >= 0 && Ordinal.count (List.tl x) >= 0
                                                                                                      ==> not
                                                                                                          (List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                           && not (List.tl (List.tl x) = [] && (List.tl x) <> [])
                                                                                                              && not (List.tl x = []))
                                                                                                          || Ordinal.<< (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                                             (Ordinal.Int (Ordinal.count x))
                                                                                                  • simplify
                                                                                                    into
                                                                                                    (not
                                                                                                     ((((List.hd x <= List.hd (List.tl x) && not (List.tl x = [] && x <> []))
                                                                                                        && not (x = []))
                                                                                                       && Ordinal.count x >= 0)
                                                                                                      && Ordinal.count (List.tl x) >= 0)
                                                                                                     || not
                                                                                                        ((List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                          && not (List.tl (List.tl x) = [] && (List.tl x) <> []))
                                                                                                         && not (List.tl x = [])))
                                                                                                    || Ordinal.<< (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                                       (Ordinal.Int (Ordinal.count x))
                                                                                                    expansions
                                                                                                    []
                                                                                                    rewrite_steps
                                                                                                      forward_chaining
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (|Ordinal.<<_114| (|Ordinal.Int_105|
                                                                                                                            (|count_`int list`_1878| (|get.::.1_1868| x…
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|count_`int list`_1878| (|get.::.1_1868| x_1869))
                                                                                                          expansions
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (|count_`int list`_1878| x_1869)
                                                                                                            expansions
                                                                                                            • unsat
                                                                                                              (let ((a!1 (>= (ite (>= (|get.::.0_1867| x_1869) 0) (|get.::.0_1867| x_1869) 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.054s):
                                                                                                             let (x : int list) = [7719; 7719; 16574; 18856; 24709]
                                                                                                            
                                                                                                            Instance
                                                                                                            proof attempt
                                                                                                            ground_instances11
                                                                                                            definitions0
                                                                                                            inductions0
                                                                                                            search_time
                                                                                                            0.054s
                                                                                                            details
                                                                                                            Expand
                                                                                                            smt_stats
                                                                                                            num checks23
                                                                                                            arith assert lower60
                                                                                                            arith pivots27
                                                                                                            rlimit count8732
                                                                                                            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
                                                                                                            memory57.410000
                                                                                                            max memory67.580000
                                                                                                            num allocs9260197867.000000
                                                                                                            Expand
                                                                                                            • start[0.054s] List.length :var_0: >= 5 && is_sorted :var_0:
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (is_sorted_1009 x_1014)
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (|List.length_1885| x_1014)
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (|List.length_1885| (|get.::.1_1884| x_1014))
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (|List.length_1885| (|get.::.1_1884| (|get.::.1_1884| x_1014)))
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (is_sorted_1009 (|get.::.1_1884| x_1014))
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (|List.length_1885|
                                                                                                                          (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| x_1014))))
                                                                                                                        expansions
                                                                                                                        • unroll
                                                                                                                          expr
                                                                                                                          (is_sorted_1009 (|get.::.1_1884| (|get.::.1_1884| x_1014)))
                                                                                                                          expansions
                                                                                                                          • unroll
                                                                                                                            expr
                                                                                                                            (let ((a!1 (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| x_1014))))))
                                                                                                                              (|List…
                                                                                                                            expansions
                                                                                                                            • unroll
                                                                                                                              expr
                                                                                                                              (is_sorted_1009 (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| x_1014))))
                                                                                                                              expansions
                                                                                                                              • unroll
                                                                                                                                expr
                                                                                                                                (let ((a!1 (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| x_1014))))))
                                                                                                                                  (|List…
                                                                                                                                expansions
                                                                                                                                • unroll
                                                                                                                                  expr
                                                                                                                                  (let ((a!1 (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| (|get.::.1_1884| x_1014))))))
                                                                                                                                    (is_so…
                                                                                                                                  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 38 steps, 0.152s):
                                                                                                                                   let (x : int list) = [6436; 6436; 6436; 6436; 6436]
                                                                                                                                  
                                                                                                                                  Instance
                                                                                                                                  proof attempt
                                                                                                                                  ground_instances38
                                                                                                                                  definitions0
                                                                                                                                  inductions0
                                                                                                                                  search_time
                                                                                                                                  0.153s
                                                                                                                                  details
                                                                                                                                  Expand
                                                                                                                                  smt_stats
                                                                                                                                  arith offset eqs100
                                                                                                                                  num checks77
                                                                                                                                  arith assert lower438
                                                                                                                                  arith pivots275
                                                                                                                                  rlimit count80889
                                                                                                                                  mk clause851
                                                                                                                                  datatype occurs check2092
                                                                                                                                  mk bool var4352
                                                                                                                                  arith assert upper539
                                                                                                                                  datatype splits906
                                                                                                                                  decisions1954
                                                                                                                                  arith add rows1296
                                                                                                                                  arith bound prop9
                                                                                                                                  propagations5259
                                                                                                                                  interface eqs83
                                                                                                                                  conflicts179
                                                                                                                                  arith fixed eqs375
                                                                                                                                  datatype accessor ax660
                                                                                                                                  minimized lits10
                                                                                                                                  arith conflicts26
                                                                                                                                  arith assert diseq108
                                                                                                                                  datatype constructor ax890
                                                                                                                                  final checks253
                                                                                                                                  added eqs9297
                                                                                                                                  del clause714
                                                                                                                                  arith eq adapter431
                                                                                                                                  memory55.550000
                                                                                                                                  max memory67.580000
                                                                                                                                  num allocs9606453469.000000
                                                                                                                                  Expand
                                                                                                                                  • start[0.153s]
                                                                                                                                      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_1898| x_1016)
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (is_sorted_1009 (|List.rev_1898| x_1016))
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (is_sorted_1009 x_1016)
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.length_1895| x_1016)
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (|List.rev_1898| (|get.::.1_1894| x_1016))
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (|List.append_1902|
                                                                                                                                                    (|List.rev_1898| (|get.::.1_1894| x_1016))
                                                                                                                                                    (|::_3| (|get.::.0_1893| x_1016) …
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (|List.length_1895| (|get.::.1_1894| x_1016))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| x_1016)))
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (|List.append_1902|
                                                                                                                                                          (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| x_1016)))
                                                                                                                                                          (|::_3| (|get.:…
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (is_sorted_1009 (|get.::.1_1894| (|List.rev_1898| x_1016)))
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (|List.length_1895| (|get.::.1_1894| (|get.::.1_1894| x_1016)))
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (is_sorted_1009 (|get.::.1_1894| x_1016))
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (|List.append_1902|
                                                                                                                                                                  (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| x_1016)))
                                                                                                                                                                  (|::_3| (|get.:…
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (let ((a!1 (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                          (a!…
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (|List.length_1895|
                                                                                                                                                                        (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (is_sorted_1009 (|get.::.1_1894| (|get.::.1_1894| x_1016)))
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                            (|List…
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                              (|List…
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (is_sorted_1009 (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| x_1016))))
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                  (|List…
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                                        (a!…
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                      (|List…
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (is_sorted_1009 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                                              (a!…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                            (|List…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                              (|List…
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                (|List…
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                  (|List…
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                    (|List…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                      (is_so…
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                                                            (a!…
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                                                              (a!…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                            (|List…
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| x_1016))))))
                                                                                                                                                                                                              (is_so…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| (|get.::.1_1894| x_1016))))))
                                                                                                                                                                                                                (|List…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|List.rev_1898| (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| x_1016)))))
                                                                                                                                                                                                                      (a!…
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1894| (|get.::.1_1894| (|get.::.1_1894| (|List.rev_1898| x_1016))))))
                                                                                                                                                                                                                    (is_so…
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • Sat (Some let (x : int list) = [6436; 6436; 6436; 6436; 6436] )

                                                                                                                                                                                                                  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 (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds x))
                                                                                                                                                                                                                  • odds (List.tl (odds x))
                                                                                                                                                                                                                  • odds (List.tl (List.tl x))
                                                                                                                                                                                                                  • odds (odds (List.tl x))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                  • merge_sort x
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • is_sorted (List.tl (List.tl (List.tl (merge_sort x))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds x)
                                                                                                                                                                                                                  • is_sorted (List.tl (merge_sort x))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (odds x))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds x))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • is_sorted (List.tl (List.tl (merge_sort x)))
                                                                                                                                                                                                                  • odds x
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (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 …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds x)))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • odds (odds x)
                                                                                                                                                                                                                  • odds (List.tl x)
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • is_sorted (merge_sort x)
                                                                                                                                                                                                                  • merge_sort (odds (odds x))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (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 (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                  • odds (odds (odds (odds …)))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds x)))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds x)))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds x)))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl x)))
                                                                                                                                                                                                                  blocked
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                  • 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 (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (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 …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (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 …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (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 …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (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 (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else List.tl (if List.hd … <= List.hd … then … else …) else (List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))))) (if List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then if List.hd … <= List.hd … then … else … else (List.tl (if List.hd … <= List.hd … then … else …))) then List.tl (if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …) else if List.hd (if List.hd … <= List.hd … then … else …) <= List.hd (if List.hd … <= List.hd … then … else …) then List.tl (if List.hd … <= List.hd … then … else …) else if List.hd … <= List.hd … then … else …)
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds 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 (List.tl (List.tl (List.tl (List.tl x))))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                  • odds (odds (odds (odds …)))
                                                                                                                                                                                                                  • odds (odds (odds (odds …)))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                  • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                  • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge_sort (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 …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • merge (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else List.tl (merge_sort …) else (List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))))) (if List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) <= List.hd (if List.hd (merge_sort …) <= List.hd (merge_sort …) then merge_sort … else (List.tl (merge_sort …))) then List.tl (if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else (merge_sort …)) else if List.hd (merge_sort …) <= List.hd (merge_sort …) then List.tl (merge_sort …) else merge_sort …)
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds (odds …)))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                  • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                  • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • merge (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then merge_sort (odds …) else (List.tl (merge_sort (odds …)))) (if List.hd (merge_sort (odds …)) <= List.hd (merge_sort (odds …)) then List.tl (merge_sort (odds …)) else (merge_sort (odds …)))
                                                                                                                                                                                                                  • is_sorted (List.tl (List.tl (List.tl (List.tl (merge_sort x)))))
                                                                                                                                                                                                                  proof attempt
                                                                                                                                                                                                                  ground_instances100
                                                                                                                                                                                                                  definitions0
                                                                                                                                                                                                                  inductions0
                                                                                                                                                                                                                  search_time
                                                                                                                                                                                                                  4.291s
                                                                                                                                                                                                                  Expand
                                                                                                                                                                                                                  • start[4.291s] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (merge_sort_1005 x_1018)
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (is_sorted_1009 (merge_sort_1005 x_1018))
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (odds_1916 (|get.::.1_1915| x_1018))
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (merge_sort_1005 (odds_1916 (|get.::.1_1915| x_1018)))
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (odds_1916 x_1018)
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (merge_sort_1005 (odds_1916 x_1018))
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (merge_982 (merge_sort_1005 (odds_1916 x_1018))
                                                                                                                                                                                                                                           (merge_sort_1005 (odds_1916 (|get.::.1_19…
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (odds_1916 (|get.::.1_1915| (|get.::.1_1915| x_1018)))
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (odds_1916 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| x_1018))))
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (is_sorted_1009 (|get.::.1_1915| (merge_sort_1005 x_1018)))
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                            (merge_sort_1005 a…
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (odds_1916 (odds_1916 (|get.::.1_1915| x_1018)))
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (odds_1916 (|get.::.1_1915| (odds_1916 x_1018)))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (merge_sort_1005 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (let ((a!1 (merge_sort_1005 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                        (a!2 (odds_1916…
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.0_1914| (merge_sort_1005 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                          (a!4 (|ge…
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (merge_sort_1005 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (odds_1916 (odds_1916 x_1018))
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (merge_sort_1005 (odds_1916 (odds_1916 x_1018)))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (let ((a!1 (merge_sort_1005 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                              (merge_982 (merge_…
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                (odds_1916 a…
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                  (odds_…
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                    (odds_1916 (…
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                      (odds_…
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1916 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                                            (a!2 (|get.::.1_1915|…
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (odds_1916 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 x_1018))))
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                            (odds_1916 a…
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                              (odds_1916 a!1))
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (is_sorted_1009 (|get.::.1_1915| (|get.::.1_1915| (merge_sort_1005 x_1018))))
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                  (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                      (merge_sort_1005 a!1))
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                            (a!2 (|get.::.1_1915|…
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                          (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                              (merge_sort_1005 a!1))
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (odds_1916 (odds_1916 (odds_1916 x_1018)))
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (merge_sort_1005 (odds_1916 (odds_1916 (odds_1916 x_1018))))
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                    (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (let ((a!1 (merge_sort_1005 (odds_1916 (odds_1916 (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                          (a!2 (odds_1916 (|get…
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (merge_sort_1005 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                            (a!2 (|get.::.0…
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                          (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                            (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                              (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (odds_1916 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1916 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                  (merge_sort_1005 a!1))
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.0_1914| (merge_sort_1005 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                                                                                        (a!3 (|ge…
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                                                                                          (a!2 (merge_sor…
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                        (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                          (merge_982 (merge_…
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (merge_sort_1005 x_1018))))))
                                                                                                                                                                                                                                                                                                                            (is_so…
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                              (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                  (odds_1916 (…
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                    (odds_1916 (…
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                      (odds_…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                        (odds_…
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                          (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                            (odds_1916 (…
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                              (odds_1916 (|get.::.1_19…
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                  (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                    (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                                                                                                                          (a!2 (odds_1916…
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                        (merge_982 (merge_sort_1…
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                                                                              (a!2 (merge_sort_1005…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                            (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                              (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1915| (|get.::.1_1915| (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                (odds_1916 (…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (odds_1916 (odds_1916 (odds_1916 (odds_1916 x_1018))))
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1916 (odds_1916 (odds_1916 (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                    (merge_sort_1005 a!1))
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1916 (odds_1916 (odds_1916 (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                                                                                          (a!2 (|get.::.1_1915| (odds…
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (merge_sort_1005 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                                                                                            (a!2 (|get.::.0…
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                          (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                            (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                              (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                    (odds_1916 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!2 (merge_so…
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                          (odds_1916 (|get.::.1_19…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                              (odds_1916 a!1))
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1916 (odds_1916 (|get.::.1_1915| (odds_1916 x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (merge_982 (merge_sort_1…
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| (odds_1916 x_1018)))))
                                                                                                                                                                                                                                                                                                                                                                                                        (a!2 (odds_1916…
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                        (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1916 (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_1005 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_1914| (merge_sort_1005 (odds_1916 (|get.::.1_1915| x_1018)))))
                                                                                                                                                                                                                                                                                                                                                                                                                  (a!3 (|ge…
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (odds_1916 (|get.:…
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!2 (odds_191…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                    (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (odds_1916 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_1005 (…
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1915| (odds_1916 (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!2 (merge_so…
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1916 (|get.::.1_1915| (odds_1916 (|get.::.1_1915| x_1018))))))
                                                                                                                                                                                                                                                                                                                                                                                                                            (odds_1916 (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions

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

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

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

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

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                          In [23]:
                                                                                                                                                                                                                                                                                                                                                                                                                          #max_induct 2;;
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          theorem merge_sorts x y =
                                                                                                                                                                                                                                                                                                                                                                                                                           is_sorted x && is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                           ==>
                                                                                                                                                                                                                                                                                                                                                                                                                           is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                          [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                          [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Out[23]:
                                                                                                                                                                                                                                                                                                                                                                                                                          val merge_sorts : int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                          Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          is_sorted x && is_sorted y ==> is_sorted (merge x y).
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                           H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                           H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                           is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                           (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                            && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                            ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                           && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                               ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                              && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                  && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> φ y x).
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                           H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                           H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                           H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                           H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                           is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                           H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                           H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                           H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                           H3. is_sorted x && is_sorted (List.tl y) ==> is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                           H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                           H5. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                           is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                          following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.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 1.2.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.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 1.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.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.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.1.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.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.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.
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                          Proved
                                                                                                                                                                                                                                                                                                                                                                                                                          proof
                                                                                                                                                                                                                                                                                                                                                                                                                          ground_instances6
                                                                                                                                                                                                                                                                                                                                                                                                                          definitions21
                                                                                                                                                                                                                                                                                                                                                                                                                          inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                          search_time
                                                                                                                                                                                                                                                                                                                                                                                                                          2.729s
                                                                                                                                                                                                                                                                                                                                                                                                                          details
                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                          smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                          num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert lower7
                                                                                                                                                                                                                                                                                                                                                                                                                          arith pivots5
                                                                                                                                                                                                                                                                                                                                                                                                                          rlimit count230655
                                                                                                                                                                                                                                                                                                                                                                                                                          mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                          datatype occurs check13
                                                                                                                                                                                                                                                                                                                                                                                                                          mk bool var79
                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert upper6
                                                                                                                                                                                                                                                                                                                                                                                                                          datatype splits3
                                                                                                                                                                                                                                                                                                                                                                                                                          decisions29
                                                                                                                                                                                                                                                                                                                                                                                                                          arith add rows14
                                                                                                                                                                                                                                                                                                                                                                                                                          propagations29
                                                                                                                                                                                                                                                                                                                                                                                                                          conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                          datatype accessor ax8
                                                                                                                                                                                                                                                                                                                                                                                                                          arith conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                          datatype constructor ax10
                                                                                                                                                                                                                                                                                                                                                                                                                          final checks4
                                                                                                                                                                                                                                                                                                                                                                                                                          added eqs72
                                                                                                                                                                                                                                                                                                                                                                                                                          del clause4
                                                                                                                                                                                                                                                                                                                                                                                                                          arith eq adapter5
                                                                                                                                                                                                                                                                                                                                                                                                                          memory58.950000
                                                                                                                                                                                                                                                                                                                                                                                                                          max memory89.010000
                                                                                                                                                                                                                                                                                                                                                                                                                          num allocs60155046938.000000
                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                          • start[2.729s, "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[2.729s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                            • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                              :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                      && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                             && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                             && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                            • Split (((((not
                                                                                                                                                                                                                                                                                                                                                                                                                                         (not
                                                                                                                                                                                                                                                                                                                                                                                                                                          ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                          && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                       || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                      && (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                            (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                             && ((not (is_sorted x) || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || is_sorted (merge x y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                           (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                            && ((not (is_sorted (List.tl x)) || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                     :cases [((((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                             (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                   (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                             (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                   (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge x y)])
                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                (((((x = [] || y = []) || List.hd y <= List.hd x) || not (not (is_sorted (List.tl x) && is_sorted y) || is_sorted (merge (List.tl x) y))) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                • start[2.492s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                    (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                       || not
                                                                                                                                                                                                                                                                                                                                                                                                                                          (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                      || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                     || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                  into
                                                                                                                                                                                                                                                                                                                                                                                                                                  ((((((((((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 (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[2.492s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                        (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not
                                                                                                                                                                                                                                                                                                                                                                                                                                              (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                      ((((((((((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[2.493s, "1.3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                               || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                          into
                                                                                                                                                                                                                                                                                                                                                                                                                                          true
                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                          merge
                                                                                                                                                                                                                                                                                                                                                                                                                                          rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                        is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[1.992s, "1"] is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                          :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                         && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • Split ((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                     (((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                       && is_sorted (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && is_sorted (merge_sort (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || is_sorted (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 :cases [not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                         || is_sorted (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                         (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                         || is_sorted (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            (((x = [] || List.tl x = [] && x <> []) || not (is_sorted (merge_sort (odds (List.tl x))))) || not (is_sorted (merge_sort (odds x)))) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[1.806s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((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 (List.tl x = [] && x <> []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[1.806s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                      not (List.tl x = [] && x <> []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                    true
                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                    [is_sorted, merge_sort, is_sorted, merge_sort, is_sorted, merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                Merge Sort contains the right elements

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                What does this mean, and why does it matter?

                                                                                                                                                                                                                                                                                                                                                                                                                                                An incorrect sorting function

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                Multiset equivalence

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                Termination proof

                                                                                                                                                                                                                                                                                                                                                                                                                                                call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                path[y <> [] && List.hd y = x && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                0.015s
                                                                                                                                                                                                                                                                                                                                                                                                                                                details
                                                                                                                                                                                                                                                                                                                                                                                                                                                Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                arith assert lower8
                                                                                                                                                                                                                                                                                                                                                                                                                                                arith pivots5
                                                                                                                                                                                                                                                                                                                                                                                                                                                rlimit count4675
                                                                                                                                                                                                                                                                                                                                                                                                                                                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
                                                                                                                                                                                                                                                                                                                                                                                                                                                memory44.710000
                                                                                                                                                                                                                                                                                                                                                                                                                                                max memory89.010000
                                                                                                                                                                                                                                                                                                                                                                                                                                                num allocs70555494364.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.<<_114| (|Ordinal.Int_105|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|count_`ty_0 list`_3947| (|get.::.1_3925| …
                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (|count_`ty_0 list`_3947| (|get.::.1_3925| y_3935))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|count_`ty_0 list`_3947| y_3935)
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (th-lemma (or (= y_3935 |[]_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.021s
                                                                                                                                                                                                                                                                                                                                                                                                                                                          details
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith assert lower5
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith pivots4
                                                                                                                                                                                                                                                                                                                                                                                                                                                          rlimit count2255
                                                                                                                                                                                                                                                                                                                                                                                                                                                          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
                                                                                                                                                                                                                                                                                                                                                                                                                                                          memory41.820000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          max memory89.010000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num allocs70190839872.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[0.021s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                              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.<<_114| (|Ordinal.Int_105|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|count_`ty_0 list`_3947| (|get.::.1_3925| …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (|count_`ty_0 list`_3947| (|get.::.1_3925| y_3935))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|count_`ty_0 list`_3947| y_3935)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (= (|count_`ty_0 list`_3947| y_3935)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (+ 1 (|count_`ty_0 list`_3947| (|get.:…

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                    In [26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem num_occur_merge a x y =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Out[26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    val num_occur_merge : int -> int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs a (merge x y) = num_occurs a x + num_occurs a y.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> φ y x a).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definition of merge to the following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.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 1.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 1.3.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0 = num_occurs a x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a x + num_occurs a (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x) + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions10
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0.297s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.297s, "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.297s, "1"] num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Split (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs a x + num_occurs a (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || num_occurs a (merge x y) = num_occurs a x + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x) + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               :cases [((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (merge x y) = num_occurs a x + num_occurs a y])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((x = [] || y = []) || List.hd y <= List.hd x) || not (num_occurs a (merge (List.tl x) y) = num_occurs a (List.tl x) + num_occurs a y)) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[0.220s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (num_occurs a (merge x (List.tl y)) = num_occurs a x + num_occurs a (List.tl y))) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.220s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []) || (List.hd y <= List.hd x && not (y = [])) && not (x = [])) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.220s, "1.3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ((((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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                This simplifies, using the definition of num_occurs to the following 2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (List.tl x) + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                We can eliminate destructors by the following substitution:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 x -> x1 :: x2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1.2':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. num_occurs a (odds x2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x2 + -1 * num_occurs a (odds (x1 :: x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C1. x1 = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Note: We must proceed by induction, but our current subgoal is less
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                appropriate for induction than our original conjecture. Thus, we prefer to
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                abandon our work until now and return our focus to the original conjecture
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                which we shall attempt to prove by induction directly.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                We shall induct according to a scheme derived from num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && not (not (x <> [] && List.hd x = a) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not (x = []) && not (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not (x = []) && (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not (not (x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                But simplification reduces this to true.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not (x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. not (List.tl x = []) && not (List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x) + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H4. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                following 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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                definitions27
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1.759s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[1.759s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    not (:var_0: = []) && not (List.tl :var_0: = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> num_occurs :var_1: (odds (List.tl :var_0:)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs :var_1: :var_0: - num_occurs :var_1: (odds :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (x = [] || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[1.759s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (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.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x) + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (((x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ((x = [] || List.tl x = []) || num_occurs a (odds (List.tl x)) = (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x)) || not (List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          start[1.614s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ((x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (1 + num_occurs a (List.tl x)) + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ((x = [] || List.tl x = []) || num_occurs a (odds (List.tl x)) = num_occurs a (List.tl x) + -1 * num_occurs a (odds x)) || List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[1.615s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ((x = [] || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  num_occurs a (List.tl x) + -1 * num_occurs a (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Elim_destructor (:cstor :: :replace x1 :: x2 :context [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (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))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs a x + -1 * num_occurs a (odds x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    And now, our second main theorem at last:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    In [28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem merge_sort_elements a (x : int list) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [@@induct functional merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Out[28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    val merge_sort_elements : int -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs a x = num_occurs a (merge_sort x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && φ (odds (List.tl x)) a && φ (odds x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ x a).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definitions of merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    and num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of merge_sort and num_occurs, and the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite rule num_occurs_arith to the following 2 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. 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.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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions15
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    7.103s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[7.103s, "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[7.103s, "1"] num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        :scheme (not (not (List.tl x = [] && x <> []) && not (x = [])) ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && φ (odds (List.tl x)) a && φ (odds x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> φ x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Split ((not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || num_occurs a x = num_occurs a (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((not (x = []) && not (List.tl x = [] && x <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs a (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && num_occurs a (odds x) = num_occurs a (merge_sort (odds x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a x = num_occurs a (merge_sort x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               :cases [not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a x = num_occurs a (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a x = num_occurs a (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((x = [] || List.tl x = [] && x <> []) || not (num_occurs a (odds (List.tl x)) = num_occurs a (merge_sort (odds (List.tl x))))) || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x)))) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[6.987s, "1.1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((x = [] || List.tl x = [] && x <> [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num_occurs a (merge_sort (odds (List.tl x)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (num_occurs a (odds x) = num_occurs a (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((((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 (List.tl x = [] && x <> []) && not (x = []) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[6.987s, "1.2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                not (List.tl x = [] && x <> []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [num_occurs, merge_sort, num_occurs, num_occurs, merge_sort, num_occurs,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs, 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)!