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.047s
details
Expand
smt_stats
num checks18
arith-assume-eqs7
arith-make-feasible139
arith-max-columns49
arith-conflicts4
rlimit count37206
arith-cheap-eqs16
mk clause192
datatype occurs check368
mk bool var550
arith-lower116
arith-diseq23
datatype splits56
decisions292
arith-propagations15
propagations301
interface eqs7
arith-bound-propagations-cheap15
arith-max-rows23
conflicts36
datatype accessor ax64
minimized lits1
arith-bound-propagations-lp2
datatype constructor ax77
num allocs897196814
final checks37
added eqs571
del clause124
arith eq adapter87
arith-upper124
memory22.650000
max memory25.440000
Expand
  • start[0.047s]
      let (_x_0 : int) = List.hd m in
      let (_x_1 : bool) = not (m = []) in
      let (_x_2 : int) = Ordinal.count l in
      let (_x_3 : int) = Ordinal.count m in
      let (_x_4 : bool) = _x_3 >= 0 in
      let (_x_5 : int list) = List.tl l in
      let (_x_6 : int) = Ordinal.count _x_5 in
      let (_x_7 : bool) = List.hd _x_5 < _x_0 in
      let (_x_8 : bool) = _x_1 && not (_x_5 = []) in
      let (_x_9 : Ordinal.t list) = [Ordinal.Int _x_3] in
      let (_x_10 : Ordinal.t list) = (Ordinal.Int _x_6) :: _x_9 in
      let (_x_11 : Ordinal.t list) = List.tl _x_10 in
      let (_x_12 : Ordinal.t) = Ordinal.Int 0 in
      let (_x_13 : Ordinal.t list) = (Ordinal.Int _x_2) :: _x_9 in
      let (_x_14 : Ordinal.t list) = List.tl _x_13 in
      List.hd l < _x_0
      && _x_1 && not (l = []) && _x_2 >= 0 && _x_4 && _x_6 >= 0 && _x_4
      ==> not (_x_7 && _x_8) && not (not _x_7 && _x_8)
          || Ordinal.( << )
             (if _x_10 = [] then _x_12
              else
              if true && _x_11 = [] then List.hd _x_10
              else if true && _x_11 <> [] && List.tl _x_11 = [] then … else …)
             (if _x_13 = [] then _x_12
              else
              if true && _x_14 = [] then List.hd _x_13
              else if true && _x_14 <> [] && List.tl _x_14 = [] then … else …)
  • simplify
    into
    let (_x_0 : int) = List.hd m in
    let (_x_1 : int list) = List.tl l in
    let (_x_2 : bool) = _x_0 <= List.hd _x_1 in
    let (_x_3 : bool) = not (m = []) in
    let (_x_4 : bool) = not (_x_1 = []) in
    let (_x_5 : int) = Ordinal.count _x_1 in
    let (_x_6 : Ordinal.t) = Ordinal.Int 1 in
    let (_x_7 : int) = Ordinal.count m in
    let (_x_8 : Ordinal.t) = Ordinal.Int _x_7 in
    let (_x_9 : int) = Ordinal.count l in
    (not ((not _x_2 && _x_3) && _x_4) && not ((_x_2 && _x_3) && _x_4)
     || Ordinal.( << )
        (Ordinal.plus (Ordinal.shift (Ordinal.Int _x_5) _x_6) _x_8)
        (Ordinal.plus (Ordinal.shift (Ordinal.Int _x_9) _x_6) _x_8))
    || not
       (((((not (_x_0 <= List.hd l) && _x_3) && not (l = [])) && _x_9 >= 0)
         && _x_7 >= 0)
        && _x_5 >= 0)
    expansions
    []
    rewrite_steps
      forward_chaining
      • unroll
        expr
        (|count_`int list`_2445| l_2432)
        expansions
        • unroll
          expr
          (|Ordinal.shift_127|
            (|Ordinal.Int_93| (|count_`int list`_2445| l_2432))
            (|Ordinal.Int_93| 1))
          expansions
          • unroll
            expr
            (|Ordinal.plus_113|
              (|Ordinal.shift_127|
                (|Ordinal.Int_93| (|count_`int list`_2445| l_2432))
             …
            expansions
            • unroll
              expr
              (|count_`int list`_2445| m_2433)
              expansions
              • unroll
                expr
                (|count_`int list`_2445| (|get.::.1_2431| l_2432))
                expansions
                • unroll
                  expr
                  (|Ordinal.shift_127|
                    (|Ordinal.Int_93| (|count_`int list`_2445| (|get.::.1_2431| l_2432)))
                    (|Ord…
                  expansions
                  • unroll
                    expr
                    (let ((a!1 (|Ordinal.shift_127|
                                 (|Ordinal.Int_93| (|count_`int list`_2445|
                                …
                    expansions
                    • unroll
                      expr
                      (let ((a!1 (|Ordinal.shift_127|
                                   (|Ordinal.Int_93| (|count_`int list`_2445|
                                  …
                      expansions
                      • Unsat

                      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_instances12
                      definitions0
                      inductions0
                      search_time
                      0.054s
                      details
                      Expand
                      smt_stats
                      num checks26
                      arith-assume-eqs9
                      arith-make-feasible256
                      arith-max-columns76
                      arith-conflicts9
                      rlimit count24133
                      arith-cheap-eqs36
                      mk clause423
                      datatype occurs check572
                      mk bool var1039
                      arith-lower266
                      arith-diseq18
                      datatype splits92
                      decisions633
                      arith-propagations16
                      propagations709
                      interface eqs9
                      arith-bound-propagations-cheap16
                      arith-max-rows37
                      conflicts49
                      datatype accessor ax125
                      minimized lits3
                      arith-bound-propagations-lp12
                      datatype constructor ax143
                      num allocs845203780
                      final checks44
                      added eqs984
                      del clause255
                      arith eq adapter192
                      arith-upper256
                      memory22.810000
                      max memory24.710000
                      Expand
                      • start[0.054s]
                          let (_x_0 : int) = List.hd l in
                          let (_x_1 : bool) = not (l = []) in
                          let (_x_2 : int) = Ordinal.count l in
                          let (_x_3 : bool) = _x_2 >= 0 in
                          let (_x_4 : int) = Ordinal.count m in
                          let (_x_5 : int list) = List.tl m in
                          let (_x_6 : int) = Ordinal.count _x_5 in
                          let (_x_7 : bool) = _x_0 < List.hd _x_5 in
                          let (_x_8 : bool) = not (_x_5 = []) && _x_1 in
                          let (_x_9 : Ordinal.t) = Ordinal.Int _x_2 in
                          let (_x_10 : Ordinal.t list) = [_x_9; Ordinal.Int _x_6] in
                          let (_x_11 : Ordinal.t list) = List.tl _x_10 in
                          let (_x_12 : Ordinal.t) = Ordinal.Int 0 in
                          let (_x_13 : Ordinal.t list) = [_x_9; Ordinal.Int _x_4] in
                          let (_x_14 : Ordinal.t list) = List.tl _x_13 in
                          not (_x_0 < List.hd m)
                          && not (m = []) && _x_1 && _x_3 && _x_4 >= 0 && _x_3 && _x_6 >= 0
                          ==> not (_x_7 && _x_8) && not (not _x_7 && _x_8)
                              || Ordinal.( << )
                                 (if _x_10 = [] then _x_12
                                  else
                                  if true && _x_11 = [] then List.hd _x_10
                                  else if true && _x_11 <> [] && List.tl _x_11 = [] then … else …)
                                 (if _x_13 = [] then _x_12
                                  else
                                  if true && _x_14 = [] then List.hd _x_13
                                  else if true && _x_14 <> [] && List.tl _x_14 = [] then … else …)
                      • simplify
                        into
                        let (_x_0 : int list) = List.tl m in
                        let (_x_1 : int) = List.hd l in
                        let (_x_2 : bool) = List.hd _x_0 <= _x_1 in
                        let (_x_3 : bool) = not (_x_0 = []) in
                        let (_x_4 : bool) = not (l = []) in
                        let (_x_5 : int) = Ordinal.count l in
                        let (_x_6 : Ordinal.t) = Ordinal.shift (Ordinal.Int _x_5) (Ordinal.Int 1) in
                        let (_x_7 : int) = Ordinal.count _x_0 in
                        let (_x_8 : int) = Ordinal.count m in
                        (not ((not _x_2 && _x_3) && _x_4) && not ((_x_2 && _x_3) && _x_4)
                         || Ordinal.( << ) (Ordinal.plus _x_6 (Ordinal.Int _x_7))
                            (Ordinal.plus _x_6 (Ordinal.Int _x_8)))
                        || not
                           (((((List.hd m <= _x_1 && not (m = [])) && _x_4) && _x_5 >= 0)
                             && _x_8 >= 0)
                            && _x_7 >= 0)
                        expansions
                        []
                        rewrite_steps
                          forward_chaining
                          • unroll
                            expr
                            (|count_`int list`_2445| m_2433)
                            expansions
                            • unroll
                              expr
                              (|Ordinal.plus_113|
                                (|Ordinal.shift_127|
                                  (|Ordinal.Int_93| (|count_`int list`_2445| l_2432))
                               …
                              expansions
                              • unroll
                                expr
                                (|count_`int list`_2445| (|get.::.1_2431| m_2433))
                                expansions
                                • unroll
                                  expr
                                  (|count_`int list`_2445| l_2432)
                                  expansions
                                  • unroll
                                    expr
                                    (|Ordinal.shift_127|
                                      (|Ordinal.Int_93| (|count_`int list`_2445| l_2432))
                                      (|Ordinal.Int_93| 1))
                                    expansions
                                    • unroll
                                      expr
                                      (|Ordinal.plus_113|
                                        (|Ordinal.shift_127|
                                          (|Ordinal.Int_93| (|count_`int list`_2445| l_2432))
                                       …
                                      expansions
                                      • unroll
                                        expr
                                        (let ((a!1 (|Ordinal.plus_113|
                                                     (|Ordinal.shift_127|
                                                       (|Ordinal.Int_93| (|…
                                        expansions
                                        • unroll
                                          expr
                                          (let ((a!1 (|get.Ordinal.Cons.2_2438|
                                                       (|Ordinal.shift_127|
                                                         (|Ordinal.Int…
                                          expansions
                                          • unroll
                                            expr
                                            (|count_`int list`_2445| (|get.::.1_2431| l_2432))
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|get.Ordinal.Cons.0_2436|
                                                           (|Ordinal.shift_127|
                                                             (|Ordinal.Int…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|get.Ordinal.Cons.2_2438|
                                                             (|Ordinal.shift_127|
                                                               (|Ordinal.Int…
                                                expansions
                                                • unroll
                                                  expr
                                                  (let ((a!1 (|Ordinal.plus_113|
                                                               (|Ordinal.shift_127|
                                                                 (|Ordinal.Int_93| (|…
                                                  expansions
                                                  • Unsat

                                                  Let's experiment a bit with merge.

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

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

                                                  Dividing into sublists

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

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

                                                  Termination proof

                                                  call `odds (List.tl (List.tl l))` from `odds l`
                                                  originalodds l
                                                  subodds (List.tl (List.tl l))
                                                  original ordinalOrdinal.Int (Ordinal.count l)
                                                  sub ordinalOrdinal.Int (Ordinal.count (List.tl (List.tl l)))
                                                  path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                  proof
                                                  detailed proof
                                                  ground_instances4
                                                  definitions0
                                                  inductions0
                                                  search_time
                                                  0.018s
                                                  details
                                                  Expand
                                                  smt_stats
                                                  num checks9
                                                  arith-assume-eqs2
                                                  arith-make-feasible24
                                                  arith-max-columns18
                                                  arith-conflicts2
                                                  rlimit count2979
                                                  arith-cheap-eqs6
                                                  mk clause25
                                                  datatype occurs check36
                                                  mk bool var100
                                                  arith-lower15
                                                  arith-diseq5
                                                  datatype splits7
                                                  decisions31
                                                  arith-propagations2
                                                  propagations14
                                                  interface eqs2
                                                  arith-bound-propagations-cheap2
                                                  arith-max-rows8
                                                  conflicts12
                                                  datatype accessor ax7
                                                  minimized lits1
                                                  arith-bound-propagations-lp1
                                                  datatype constructor ax15
                                                  num allocs924678053
                                                  final checks10
                                                  added eqs74
                                                  del clause17
                                                  arith eq adapter12
                                                  arith-upper16
                                                  memory25.530000
                                                  max memory25.530000
                                                  Expand
                                                  • start[0.018s]
                                                      let (_x_0 : ty_0 list) = List.tl l in
                                                      let (_x_1 : int) = Ordinal.count l in
                                                      let (_x_2 : ty_0 list) = List.tl _x_0 in
                                                      let (_x_3 : int) = Ordinal.count _x_2 in
                                                      not (l <> [] && _x_0 = []) && not (l = []) && _x_1 >= 0 && _x_3 >= 0
                                                      ==> not (not (_x_2 <> [] && List.tl _x_2 = []) && not (_x_2 = []))
                                                          || Ordinal.( << ) (Ordinal.Int _x_3) (Ordinal.Int _x_1)
                                                  • simplify
                                                    into
                                                    let (_x_0 : ty_0 list) = List.tl l in
                                                    let (_x_1 : ty_0 list) = List.tl _x_0 in
                                                    let (_x_2 : int) = Ordinal.count _x_1 in
                                                    let (_x_3 : int) = Ordinal.count l in
                                                    (not (not (_x_1 <> [] && List.tl _x_1 = []) && not (_x_1 = []))
                                                     || Ordinal.( << ) (Ordinal.Int _x_2) (Ordinal.Int _x_3))
                                                    || not
                                                       (((not (l <> [] && _x_0 = []) && not (l = [])) && _x_3 >= 0) && _x_2 >= 0)
                                                    expansions
                                                    []
                                                    rewrite_steps
                                                      forward_chaining
                                                      • unroll
                                                        expr
                                                        (|count_`ty_0 list`_2635| l_2626)
                                                        expansions
                                                        • unroll
                                                          expr
                                                          (|count_`ty_0 list`_2635| (|get.::.1_2619| (|get.::.1_2619| l_2626)))
                                                          expansions
                                                          • unroll
                                                            expr
                                                            (let ((a!1 (|Ordinal.Int_93| (|count_`ty_0 list`_2635|
                                                                                           (|get.::.1_261…
                                                            expansions
                                                            • unroll
                                                              expr
                                                              (|count_`ty_0 list`_2635| (|get.::.1_2619| l_2626))
                                                              expansions
                                                              • Unsat

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

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

                                                              Defining Merge Sort

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

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

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

                                                              In [9]:
                                                              let merge_sort_measure x =
                                                               Ordinal.of_int (List.length x)
                                                              
                                                              Out[9]:
                                                              val merge_sort_measure : 'a list -> Ordinal.t = <fun>
                                                              
                                                              In [10]:
                                                              theorem odds_len_1 x =
                                                               x <> [] && List.tl x <> []
                                                               ==>
                                                               (List.length (odds x) [@trigger]) < List.length x
                                                              [@@induct functional odds] [@@forward_chaining]
                                                              
                                                              Out[10]:
                                                              val odds_len_1 : 'a list -> bool = <fun>
                                                              Goal:
                                                              
                                                              x <> [] && List.tl x <> [] ==> List.length (odds x) < List.length x.
                                                              
                                                              1 nontautological subgoal.
                                                              
                                                              We shall induct according to a scheme derived from odds.
                                                              
                                                              Induction scheme:
                                                              
                                                               (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                               && (not (x = [])
                                                                   && not (x <> [] && List.tl x = []) && φ (List.tl (List.tl x)) ==> 
                                                                   φ x).
                                                              
                                                              2 nontautological subgoals.
                                                              
                                                              Subgoal 2:
                                                              
                                                               H0. List.length x <= List.length (odds x)
                                                               H1. not (x = [])
                                                               H2. not (List.tl x = [])
                                                              |---------------------------------------------------------------------------
                                                               not (x <> [] && List.tl x = []) && not (x = [])
                                                              
                                                              But simplification reduces this to true, using the forward-chaining rule
                                                              List.len_nonnegative.
                                                              
                                                              Subgoal 1:
                                                              
                                                               H0. List.length x <= List.length (odds x)
                                                               H1. not (x = [])
                                                               H2. not (List.tl x = [])
                                                               H3. not (x = [])
                                                               H4. not (x <> [] && List.tl x = [])
                                                               H5. not
                                                                   (List.length (List.tl (List.tl x)) <=
                                                                    List.length (odds (List.tl (List.tl x))))
                                                                   || not
                                                                      (not (List.tl (List.tl x) = [])
                                                                       && not (List.tl (List.tl (List.tl x)) = []))
                                                              |---------------------------------------------------------------------------
                                                               false
                                                              
                                                              This simplifies, using the definitions of List.length and odds to the
                                                              following 3 subgoals:
                                                              
                                                              Subgoal 1.3:
                                                              
                                                               H0. (List.tl x) <> []
                                                               H1. x <> []
                                                               H2. List.length (List.tl (List.tl x)) <=
                                                                   List.length (odds (List.tl (List.tl x)))
                                                               H3. List.tl (List.tl x) = []
                                                               H4. 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. (List.tl x) <> []
                                                               H1. x <> []
                                                               H2. List.length (List.tl (List.tl x)) <=
                                                                   List.length (odds (List.tl (List.tl x)))
                                                               H3. (List.tl (List.tl x)) <> []
                                                               H4. List.tl (List.tl (List.tl x)) = []
                                                               H5. 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.2':
                                                              
                                                               H0. List.tl (List.tl (List.tl x)) = []
                                                               H1. x <> []
                                                               H2. (List.tl x) <> []
                                                               H3. (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.
                                                              
                                                              Subgoal 1.1:
                                                              
                                                               H0. (List.tl x) <> []
                                                               H1. x <> []
                                                               H2. 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)))
                                                              
                                                              But simplification reduces this to true, using the definition of List.length.
                                                              
                                                               Rules:
                                                                  (:def List.length)
                                                                  (:def odds)
                                                                  (:fc List.len_nonnegative)
                                                                  (:induct odds)
                                                              
                                                              
                                                              Proved
                                                              proof
                                                              ground_instances0
                                                              definitions20
                                                              inductions1
                                                              search_time
                                                              0.626s
                                                              Expand
                                                              • start[0.626s, "Goal"]
                                                                  not (:var_0: = []) && not (List.tl :var_0: = [])
                                                                  ==> List.length (odds :var_0:) < List.length :var_0:
                                                              • subproof

                                                                (not (List.length x <= List.length (odds x)) || x = []) || List.tl x = []
                                                                • start[0.626s, "1"]
                                                                    (not (List.length x <= List.length (odds x)) || x = []) || List.tl x = []
                                                                • induction on (functional odds)
                                                                  :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                          && (not (x = [])
                                                                              && not (x <> [] && List.tl x = []) && φ (List.tl (List.tl x))
                                                                              ==> φ x)
                                                                • Split (let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                         let (_x_1 : bool) = _x_0 = [] in
                                                                         let (_x_2 : bool) = not (x <> [] && _x_1) in
                                                                         let (_x_3 : bool) = not (x = []) in
                                                                         let (_x_4 : bool) = not (List.length x <= List.length (odds x)) in
                                                                         let (_x_5 : bool) = not (_x_3 && not _x_1) in
                                                                         let (_x_6 : sko_ty_0 list) = List.tl _x_0 in
                                                                         ((_x_2 && _x_3 || _x_4) || _x_5)
                                                                         && ((_x_4 || _x_5)
                                                                             || not
                                                                                ((_x_3 && _x_2)
                                                                                 && (not (List.length _x_6 <= List.length (odds _x_6))
                                                                                     || not (not (_x_6 = []) && not (List.tl _x_6 = [])))))
                                                                         :cases [let (_x_0 : bool) = x = [] in
                                                                                 let (_x_1 : bool) = List.tl x = [] in
                                                                                 ((not (List.length x <= List.length (odds x)) || _x_0) || _x_1)
                                                                                 || not (x <> [] && _x_1) && not _x_0;
                                                                                 let (_x_0 : bool) = x = [] in
                                                                                 let (_x_1 : sko_ty_0 list) = List.tl x in
                                                                                 let (_x_2 : bool) = _x_1 = [] in
                                                                                 let (_x_3 : sko_ty_0 list) = List.tl _x_1 in
                                                                                 ((((not (List.length x <= List.length (odds x)) || _x_0)
                                                                                    || _x_2)
                                                                                   || _x_0)
                                                                                  || x <> [] && _x_2)
                                                                                 || not
                                                                                    (not (List.length _x_3 <= List.length (odds _x_3))
                                                                                     || not (not (_x_3 = []) && not (List.tl _x_3 = [])))])
                                                                  • subproof
                                                                    let (_x_0 : bool) = x = [] in let (_x_1 : sko_ty_0 list) = List.tl x in let (_x_2 : bool) = _x_1 = [] in let (_x_3 : sko_ty_0 list) = List.tl _x_1 in ((((not (List.length x <= List.length (odds x)) || _x_0) || _x_2) || _x_0) || x <> [] && _x_2) || not (not (List.length _x_3 <= List.length (odds _x_3)) || not (not (_x_3 = []) && not (List.tl _x_3 = [])))
                                                                    • start[0.624s, "1"]
                                                                        let (_x_0 : bool) = x = [] in
                                                                        let (_x_1 : sko_ty_0 list) = List.tl x in
                                                                        let (_x_2 : bool) = _x_1 = [] in
                                                                        let (_x_3 : sko_ty_0 list) = List.tl _x_1 in
                                                                        ((((not (List.length x <= List.length (odds x)) || _x_0) || _x_2) || _x_0)
                                                                         || x <> [] && _x_2)
                                                                        || not
                                                                           (not (List.length _x_3 <= List.length (odds _x_3))
                                                                            || not (not (_x_3 = []) && not (List.tl _x_3 = [])))
                                                                    • simplify
                                                                      into
                                                                      let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                      let (_x_1 : bool) = _x_0 = [] || x = [] in
                                                                      let (_x_2 : sko_ty_0 list) = List.tl _x_0 in
                                                                      let (_x_3 : int) = List.length (odds _x_2) in
                                                                      let (_x_4 : bool) = List.length _x_2 <= _x_3 in
                                                                      let (_x_5 : bool) = _x_1 || not _x_4 in
                                                                      let (_x_6 : bool) = _x_2 = [] in
                                                                      let (_x_7 : bool) = not (List.length _x_0 <= _x_3) in
                                                                      (((_x_5 || not _x_6) || _x_7)
                                                                       && (((_x_5 || _x_6) || not (List.tl _x_2 = [])) || _x_7))
                                                                      && ((_x_1 || _x_4) || _x_7)
                                                                      expansions
                                                                      [List.length, odds, List.length, List.length, odds, List.length, List.length,
                                                                       odds, List.length]
                                                                      rewrite_steps
                                                                        forward_chaining
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • List.len_nonnegative
                                                                        • 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
                                                                      let (_x_0 : bool) = x = [] in let (_x_1 : bool) = List.tl x = [] in ((not (List.length x <= List.length (odds x)) || _x_0) || _x_1) || not (x <> [] && _x_1) && not _x_0
                                                                      • start[0.624s, "2"]
                                                                          let (_x_0 : bool) = x = [] in
                                                                          let (_x_1 : bool) = List.tl x = [] in
                                                                          ((not (List.length x <= List.length (odds x)) || _x_0) || _x_1)
                                                                          || not (x <> [] && _x_1) && not _x_0
                                                                      • simplify
                                                                        into
                                                                        true
                                                                        expansions
                                                                        []
                                                                        rewrite_steps
                                                                          forward_chaining
                                                                          • List.len_nonnegative
                                                                          • List.len_nonnegative

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

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

                                                                  Termination proof

                                                                  call `merge_sort (odds l)` from `merge_sort l`
                                                                  originalmerge_sort l
                                                                  submerge_sort (odds l)
                                                                  original ordinalmerge_sort_measure l
                                                                  sub ordinalmerge_sort_measure (odds l)
                                                                  path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                                  proof
                                                                  detailed proof
                                                                  ground_instances3
                                                                  definitions0
                                                                  inductions0
                                                                  search_time
                                                                  0.020s
                                                                  details
                                                                  Expand
                                                                  smt_stats
                                                                  num checks7
                                                                  arith-make-feasible12
                                                                  arith-max-columns11
                                                                  rlimit count6363
                                                                  mk clause11
                                                                  datatype occurs check53
                                                                  mk bool var70
                                                                  arith-lower2
                                                                  datatype splits11
                                                                  decisions20
                                                                  propagations7
                                                                  arith-max-rows3
                                                                  conflicts10
                                                                  datatype accessor ax7
                                                                  datatype constructor ax18
                                                                  final checks10
                                                                  added eqs55
                                                                  del clause11
                                                                  arith eq adapter2
                                                                  arith-upper7
                                                                  memory45.450000
                                                                  max memory71.030000
                                                                  num allocs5558315704.000000
                                                                  Expand
                                                                  • start[0.020s]
                                                                      let (_x_0 : int) = List.length l in
                                                                      let (_x_1 : int) = if _x_0 >= 0 then _x_0 else 0 in
                                                                      let (_x_2 : int list) = odds l in
                                                                      let (_x_3 : int) = List.length _x_2 in
                                                                      let (_x_4 : int) = if _x_3 >= 0 then _x_3 else 0 in
                                                                      let (_x_5 : bool)
                                                                          = not (not (_x_2 <> [] && List.tl _x_2 = []) && not (_x_2 = []))
                                                                      in
                                                                      not (l <> [] && List.tl l = []) && not (l = []) && _x_1 >= 0 && _x_4 >= 0
                                                                      ==> _x_5 && _x_5 || Ordinal.( << ) (Ordinal.Int _x_4) (Ordinal.Int _x_1)
                                                                  • simplify
                                                                    into
                                                                    let (_x_0 : int list) = odds l in
                                                                    let (_x_1 : int) = List.length _x_0 in
                                                                    let (_x_2 : int) = List.length l in
                                                                    (not (not (l <> [] && List.tl l = []) && not (l = []))
                                                                     || not (not (_x_0 <> [] && List.tl _x_0 = []) && not (_x_0 = [])))
                                                                    || Ordinal.( << ) (Ordinal.Int (if _x_1 >= 0 then _x_1 else 0))
                                                                       (Ordinal.Int (if _x_2 >= 0 then _x_2 else 0))
                                                                    expansions
                                                                    []
                                                                    rewrite_steps
                                                                      forward_chaining
                                                                      • unroll
                                                                        expr
                                                                        (|List.length_3044| l_3054)
                                                                        expansions
                                                                        • unroll
                                                                          expr
                                                                          (|List.length_3044| (odds_3048 l_3054))
                                                                          expansions
                                                                          • unroll
                                                                            expr
                                                                            (let ((a!1 (ite (>= (|List.length_3044| (odds_3048 l_3054)) 0)
                                                                                            (|List.length_3044| (…
                                                                            expansions
                                                                            • Unsat

                                                                            call `merge_sort (odds (List.tl l))` from `merge_sort l`
                                                                            originalmerge_sort l
                                                                            submerge_sort (odds (List.tl l))
                                                                            original ordinalmerge_sort_measure l
                                                                            sub ordinalmerge_sort_measure (odds (List.tl l))
                                                                            path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                                            proof
                                                                            detailed proof
                                                                            ground_instances4
                                                                            definitions0
                                                                            inductions0
                                                                            search_time
                                                                            0.023s
                                                                            details
                                                                            Expand
                                                                            smt_stats
                                                                            num checks10
                                                                            arith-assume-eqs2
                                                                            arith-make-feasible20
                                                                            arith-max-columns12
                                                                            rlimit count3758
                                                                            arith-cheap-eqs4
                                                                            mk clause24
                                                                            datatype occurs check99
                                                                            mk bool var149
                                                                            arith-lower11
                                                                            datatype splits27
                                                                            decisions39
                                                                            propagations29
                                                                            interface eqs2
                                                                            arith-max-rows4
                                                                            conflicts16
                                                                            datatype accessor ax20
                                                                            arith-bound-propagations-lp1
                                                                            datatype constructor ax34
                                                                            final checks20
                                                                            added eqs144
                                                                            del clause17
                                                                            arith eq adapter4
                                                                            arith-upper8
                                                                            memory42.880000
                                                                            max memory71.030000
                                                                            num allocs5486678963.000000
                                                                            Expand
                                                                            • start[0.023s]
                                                                                let (_x_0 : int list) = List.tl l in
                                                                                let (_x_1 : int) = List.length l in
                                                                                let (_x_2 : int) = if _x_1 >= 0 then _x_1 else 0 in
                                                                                let (_x_3 : int list) = odds _x_0 in
                                                                                let (_x_4 : int) = List.length _x_3 in
                                                                                let (_x_5 : int) = if _x_4 >= 0 then _x_4 else 0 in
                                                                                let (_x_6 : bool)
                                                                                    = not (not (_x_3 <> [] && List.tl _x_3 = []) && not (_x_3 = []))
                                                                                in
                                                                                not (l <> [] && _x_0 = []) && not (l = []) && _x_2 >= 0 && _x_5 >= 0
                                                                                ==> _x_6 && _x_6 || Ordinal.( << ) (Ordinal.Int _x_5) (Ordinal.Int _x_2)
                                                                            • simplify
                                                                              into
                                                                              let (_x_0 : int list) = List.tl l in
                                                                              let (_x_1 : int list) = odds _x_0 in
                                                                              let (_x_2 : int) = List.length _x_1 in
                                                                              let (_x_3 : int) = List.length l in
                                                                              (not (not (_x_1 <> [] && List.tl _x_1 = []) && not (_x_1 = []))
                                                                               || Ordinal.( << ) (Ordinal.Int (if _x_2 >= 0 then _x_2 else 0))
                                                                                  (Ordinal.Int (if _x_3 >= 0 then _x_3 else 0)))
                                                                              || not (not (l <> [] && _x_0 = []) && not (l = []))
                                                                              expansions
                                                                              []
                                                                              rewrite_steps
                                                                                forward_chaining
                                                                                • unroll
                                                                                  expr
                                                                                  (|List.length_3044| l_3054)
                                                                                  expansions
                                                                                  • unroll
                                                                                    expr
                                                                                    (|List.length_3044| (odds_3048 (|get.::.1_3037| l_3054)))
                                                                                    expansions
                                                                                    • unroll
                                                                                      expr
                                                                                      (let ((a!1 (>= (|List.length_3044| (odds_3048 (|get.::.1_3037| l_3054))) 0))
                                                                                            (a!3 (|Ordinal.In…
                                                                                      expansions
                                                                                      • unroll
                                                                                        expr
                                                                                        (odds_3048 (|get.::.1_3037| l_3054))
                                                                                        expansions
                                                                                        • Unsat

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

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

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

                                                                                        Proving Merge Sort correct

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

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

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

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

                                                                                        Termination proof

                                                                                        call `is_sorted (List.tl x)` from `is_sorted x`
                                                                                        originalis_sorted x
                                                                                        subis_sorted (List.tl x)
                                                                                        original ordinalOrdinal.Int (Ordinal.count x)
                                                                                        sub ordinalOrdinal.Int (Ordinal.count (List.tl x))
                                                                                        path[List.hd x <= List.hd (List.tl x) && not (x <> [] && List.tl x = []) && not (x = [])]
                                                                                        proof
                                                                                        detailed proof
                                                                                        ground_instances3
                                                                                        definitions0
                                                                                        inductions0
                                                                                        search_time
                                                                                        0.015s
                                                                                        details
                                                                                        Expand
                                                                                        smt_stats
                                                                                        num checks8
                                                                                        arith-make-feasible19
                                                                                        arith-max-columns22
                                                                                        arith-conflicts2
                                                                                        rlimit count2716
                                                                                        mk clause15
                                                                                        datatype occurs check19
                                                                                        mk bool var76
                                                                                        arith-lower16
                                                                                        arith-diseq1
                                                                                        datatype splits3
                                                                                        decisions20
                                                                                        propagations15
                                                                                        arith-max-rows9
                                                                                        conflicts11
                                                                                        datatype accessor ax6
                                                                                        arith-bound-propagations-lp1
                                                                                        datatype constructor ax10
                                                                                        final checks5
                                                                                        added eqs52
                                                                                        del clause6
                                                                                        arith eq adapter11
                                                                                        arith-upper14
                                                                                        memory43.250000
                                                                                        max memory71.030000
                                                                                        num allocs5780014691.000000
                                                                                        Expand
                                                                                        • start[0.015s]
                                                                                            let (_x_0 : int list) = List.tl x in
                                                                                            let (_x_1 : int) = List.hd _x_0 in
                                                                                            let (_x_2 : bool) = _x_0 = [] in
                                                                                            let (_x_3 : int) = Ordinal.count x in
                                                                                            let (_x_4 : int) = Ordinal.count _x_0 in
                                                                                            let (_x_5 : int list) = List.tl _x_0 in
                                                                                            List.hd x <= _x_1
                                                                                            && not (x <> [] && _x_2) && not (x = []) && _x_3 >= 0 && _x_4 >= 0
                                                                                            ==> not (_x_1 <= List.hd _x_5 && not (_x_0 <> [] && _x_5 = []) && not _x_2)
                                                                                                || Ordinal.( << ) (Ordinal.Int _x_4) (Ordinal.Int _x_3)
                                                                                        • simplify
                                                                                          into
                                                                                          let (_x_0 : int list) = List.tl x in
                                                                                          let (_x_1 : int) = Ordinal.count _x_0 in
                                                                                          let (_x_2 : int) = Ordinal.count x in
                                                                                          let (_x_3 : int) = List.hd _x_0 in
                                                                                          let (_x_4 : int list) = List.tl _x_0 in
                                                                                          let (_x_5 : bool) = _x_0 = [] in
                                                                                          (Ordinal.( << ) (Ordinal.Int _x_1) (Ordinal.Int _x_2)
                                                                                           || not ((_x_3 <= List.hd _x_4 && not (_x_0 <> [] && _x_4 = [])) && not _x_5))
                                                                                          || not
                                                                                             ((((List.hd x <= _x_3 && not (x <> [] && _x_5)) && not (x = []))
                                                                                               && _x_2 >= 0)
                                                                                              && _x_1 >= 0)
                                                                                          expansions
                                                                                          []
                                                                                          rewrite_steps
                                                                                            forward_chaining
                                                                                            • unroll
                                                                                              expr
                                                                                              (|count_`int list`_3144| x_3135)
                                                                                              expansions
                                                                                              • unroll
                                                                                                expr
                                                                                                (|count_`int list`_3144| (|get.::.1_3134| x_3135))
                                                                                                expansions
                                                                                                • unroll
                                                                                                  expr
                                                                                                  (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`int list`_3144|
                                                                                                                                        (…
                                                                                                  expansions
                                                                                                  • Unsat

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

                                                                                                  In [15]:
                                                                                                  is_sorted [1;2;3;4;5]
                                                                                                  
                                                                                                  Out[15]:
                                                                                                  - : bool = true
                                                                                                  
                                                                                                  In [16]:
                                                                                                  is_sorted [1;4;2]
                                                                                                  
                                                                                                  Out[16]:
                                                                                                  - : bool = false
                                                                                                  
                                                                                                  In [17]:
                                                                                                  is_sorted [1]
                                                                                                  
                                                                                                  Out[17]:
                                                                                                  - : bool = true
                                                                                                  
                                                                                                  In [18]:
                                                                                                  instance (fun x -> List.length x >= 5 && is_sorted x)
                                                                                                  
                                                                                                  Out[18]:
                                                                                                  - : int list -> bool = <fun>
                                                                                                  module CX : sig val x : int list end
                                                                                                  
                                                                                                  Instance (after 11 steps, 0.030s):
                                                                                                   let (x : int list) = [121961; 121961; 121961; 121961; 121961]
                                                                                                  
                                                                                                  Instance
                                                                                                  proof attempt
                                                                                                  ground_instances11
                                                                                                  definitions0
                                                                                                  inductions0
                                                                                                  search_time
                                                                                                  0.030s
                                                                                                  details
                                                                                                  Expand
                                                                                                  smt_stats
                                                                                                  num checks23
                                                                                                  arith-assume-eqs22
                                                                                                  arith-make-feasible131
                                                                                                  arith-max-columns35
                                                                                                  arith-conflicts5
                                                                                                  rlimit count8763
                                                                                                  arith-cheap-eqs26
                                                                                                  mk clause258
                                                                                                  datatype occurs check96
                                                                                                  mk bool var532
                                                                                                  arith-lower79
                                                                                                  arith-diseq30
                                                                                                  datatype splits47
                                                                                                  decisions146
                                                                                                  arith-propagations14
                                                                                                  propagations537
                                                                                                  interface eqs22
                                                                                                  arith-bound-propagations-cheap14
                                                                                                  arith-max-rows18
                                                                                                  conflicts44
                                                                                                  datatype accessor ax42
                                                                                                  minimized lits2
                                                                                                  arith-bound-propagations-lp6
                                                                                                  datatype constructor ax57
                                                                                                  final checks57
                                                                                                  added eqs495
                                                                                                  del clause219
                                                                                                  arith eq adapter114
                                                                                                  arith-upper120
                                                                                                  memory43.680000
                                                                                                  max memory71.030000
                                                                                                  num allocs5936637045.000000
                                                                                                  Expand
                                                                                                  • start[0.030s] List.length :var_0: >= 5 && is_sorted :var_0:
                                                                                                  • unroll
                                                                                                    expr
                                                                                                    (is_sorted_41 x_46)
                                                                                                    expansions
                                                                                                    • unroll
                                                                                                      expr
                                                                                                      (|List.length_3187| x_46)
                                                                                                      expansions
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (|List.length_3187| (|get.::.1_3186| x_46))
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|List.length_3187| (|get.::.1_3186| (|get.::.1_3186| x_46)))
                                                                                                          expansions
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (is_sorted_41 (|get.::.1_3186| x_46))
                                                                                                            expansions
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (|List.length_3187| (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| x_46))))
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (is_sorted_41 (|get.::.1_3186| (|get.::.1_3186| x_46)))
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (let ((a!1 (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| x_46))))))
                                                                                                                    (|List.l…
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (is_sorted_41 (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| x_46))))
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (let ((a!1 (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| x_46))))))
                                                                                                                        (|List.l…
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (let ((a!1 (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| (|get.::.1_3186| x_46))))))
                                                                                                                          (is_sort…
                                                                                                                        expansions
                                                                                                                        • Sat (Some let (x : int list) = [121961; 121961; 121961; 121961; 121961] )
                                                                                                                        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 45 steps, 0.145s):
                                                                                                                         let (x : int list) = [780042; 780042; 780042; 780042; 780042]
                                                                                                                        
                                                                                                                        Instance
                                                                                                                        proof attempt
                                                                                                                        ground_instances45
                                                                                                                        definitions0
                                                                                                                        inductions0
                                                                                                                        search_time
                                                                                                                        0.145s
                                                                                                                        details
                                                                                                                        Expand
                                                                                                                        smt_stats
                                                                                                                        num checks91
                                                                                                                        arith-assume-eqs135
                                                                                                                        arith-make-feasible797
                                                                                                                        arith-max-columns62
                                                                                                                        arith-conflicts17
                                                                                                                        rlimit count86876
                                                                                                                        arith-cheap-eqs211
                                                                                                                        mk clause1076
                                                                                                                        datatype occurs check3401
                                                                                                                        mk bool var5331
                                                                                                                        arith-lower676
                                                                                                                        arith-diseq150
                                                                                                                        datatype splits1181
                                                                                                                        decisions2996
                                                                                                                        arith-propagations130
                                                                                                                        propagations7069
                                                                                                                        interface eqs135
                                                                                                                        arith-bound-propagations-cheap130
                                                                                                                        arith-max-rows37
                                                                                                                        conflicts212
                                                                                                                        datatype accessor ax841
                                                                                                                        minimized lits20
                                                                                                                        arith-bound-propagations-lp19
                                                                                                                        datatype constructor ax1161
                                                                                                                        final checks342
                                                                                                                        added eqs12556
                                                                                                                        del clause768
                                                                                                                        arith eq adapter469
                                                                                                                        arith-upper566
                                                                                                                        memory45.210000
                                                                                                                        max memory71.030000
                                                                                                                        num allocs6132822615.000000
                                                                                                                        Expand
                                                                                                                        • start[0.145s]
                                                                                                                            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_3214| x_48)
                                                                                                                              expansions
                                                                                                                              • unroll
                                                                                                                                expr
                                                                                                                                (is_sorted_41 (|List.rev_3214| x_48))
                                                                                                                                expansions
                                                                                                                                • unroll
                                                                                                                                  expr
                                                                                                                                  (is_sorted_41 x_48)
                                                                                                                                  expansions
                                                                                                                                  • unroll
                                                                                                                                    expr
                                                                                                                                    (|List.length_3211| x_48)
                                                                                                                                    expansions
                                                                                                                                    • unroll
                                                                                                                                      expr
                                                                                                                                      (|List.rev_3214| (|get.::.1_3210| x_48))
                                                                                                                                      expansions
                                                                                                                                      • unroll
                                                                                                                                        expr
                                                                                                                                        (|List.append_3218|
                                                                                                                                          (|List.rev_3214| (|get.::.1_3210| x_48))
                                                                                                                                          (|::_3| (|get.::.0_3209| x_48) |[]_…
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (|List.length_3211| (|get.::.1_3210| x_48))
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48)))
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.append_3218|
                                                                                                                                                (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48)))
                                                                                                                                                (|::_3| (|get.::.…
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (is_sorted_41 (|get.::.1_3210| (|List.rev_3214| x_48)))
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (|List.length_3211| (|get.::.1_3210| (|get.::.1_3210| x_48)))
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (is_sorted_41 (|get.::.1_3210| x_48))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (|List.append_3218|
                                                                                                                                                        (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| x_48)))
                                                                                                                                                        (|::_3| (|get.::.…
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (let ((a!1 (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                (a!2 …
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (|List.length_3211| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (let ((a!1 (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                (|List.a…
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (is_sorted_41 (|get.::.1_3210| (|get.::.1_3210| x_48)))
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                    (|List.r…
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (is_sorted_41 (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| x_48))))
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                            (a!2 …
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                          (|List.l…
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                                (a!2 …
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (let ((a!1 (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                              (|List.a…
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                (|List.a…
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (is_sorted_41 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                    (|List.r…
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                      (|List.a…
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                        (|List.l…
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| x_48))))))
                                                                                                                                                                                          (is_sort…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                            (is_sort…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                                                  (a!2 …
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                                                    (a!2 …
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                  (|List.a…
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                      (|List.r…
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                          (|List.a…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                            (|List.l…
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| x_48))))))
                                                                                                                                                                                                              (is_sort…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                                (is_sort…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| (|get.::.1_3210| x_48)))))
                                                                                                                                                                                                                        (a!2 …
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                                      (|List.a…
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_3210| (|get.::.1_3210| (|List.rev_3214| (|get.::.1_3210| x_48))))))
                                                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • Sat (Some let (x : int list) = [780042; 780042; 780042; 780042; 780042] )

                                                                                                                                                                                                                      Proving Merge Sort sorts

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

                                                                                                                                                                                                                      We can write this this way:

                                                                                                                                                                                                                      theorem merge_sort_sorts x =
                                                                                                                                                                                                                       is_sorted (merge_sort x)
                                                                                                                                                                                                                      

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

                                                                                                                                                                                                                      In [20]:
                                                                                                                                                                                                                      verify (fun x -> is_sorted (merge_sort x))
                                                                                                                                                                                                                      
                                                                                                                                                                                                                      Out[20]:
                                                                                                                                                                                                                      - : int list -> bool = <fun>
                                                                                                                                                                                                                      
                                                                                                                                                                                                                      Unknown (Verified up to bound 100)
                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                      expanded
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (odds x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds x)))
                                                                                                                                                                                                                      • merge_sort x
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds x)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (List.tl (merge_sort x))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds x in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl x) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds x))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds x))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds x))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl (odds (List.tl x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (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 (odds x))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl x)) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (List.tl x))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds x) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds x)))
                                                                                                                                                                                                                      • is_sorted (List.tl (merge_sort x))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds x))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl x))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds x)) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (merge_sort x)))
                                                                                                                                                                                                                      • odds (odds x)
                                                                                                                                                                                                                      • odds (odds (List.tl x))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds x))))
                                                                                                                                                                                                                      • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • 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 (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl x))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl x)))
                                                                                                                                                                                                                      • odds x
                                                                                                                                                                                                                      • odds (List.tl x)
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl x) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds x in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds x))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds x)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds (List.tl x))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds x)) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = merge_sort (odds x) in let (_x_1 : int list) = merge_sort (odds (List.tl x)) in let (_x_2 : bool) = List.hd _x_1 <= List.hd _x_0 in merge (if _x_2 then _x_0 else (List.tl _x_0)) (if _x_2 then List.tl _x_1 else _x_1)
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds x)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds x))))
                                                                                                                                                                                                                      • is_sorted (merge_sort x)
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                      • odds (odds (odds x))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds x))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl x) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in let (_x_4 : int list) = if _x_3 then _x_1 else List.tl _x_1 in let (_x_5 : int list) = if _x_3 then List.tl _x_2 else _x_2 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_4 in merge (if _x_6 then _x_4 else (List.tl _x_4)) (if _x_6 then List.tl _x_5 else _x_5)
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds x in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in let (_x_4 : int list) = if _x_3 then _x_1 else List.tl _x_1 in let (_x_5 : int list) = if _x_3 then List.tl _x_2 else _x_2 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_4 in merge (if _x_6 then _x_4 else (List.tl _x_4)) (if _x_6 then List.tl _x_5 else _x_5)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds x) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (odds (odds (odds (List.tl x))))
                                                                                                                                                                                                                      • odds (odds (odds (odds x)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = merge_sort (odds x) in let (_x_1 : int list) = merge_sort (odds (List.tl x)) in let (_x_2 : bool) = List.hd _x_1 <= List.hd _x_0 in let (_x_3 : int list) = if _x_2 then _x_0 else List.tl _x_0 in let (_x_4 : int list) = if _x_2 then List.tl _x_1 else _x_1 in let (_x_5 : bool) = List.hd _x_4 <= List.hd _x_3 in merge (if _x_5 then _x_3 else (List.tl _x_3)) (if _x_5 then List.tl _x_4 else _x_4)
                                                                                                                                                                                                                      • merge_sort (odds x)
                                                                                                                                                                                                                      • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                      blocked
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds (odds x)))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl x) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in let (_x_4 : int list) = if _x_3 then _x_1 else List.tl _x_1 in let (_x_5 : int list) = if _x_3 then List.tl _x_2 else _x_2 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_4 in let (_x_7 : int list) = if _x_6 then _x_4 else List.tl _x_4 in let (_x_8 : int list) = if _x_6 then List.tl _x_5 else _x_5 in let (_x_9 : bool) = List.hd _x_8 <= List.hd _x_7 in merge (if _x_9 then _x_7 else (List.tl _x_7)) (if _x_9 then List.tl _x_8 else _x_8)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds x in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in let (_x_4 : int list) = if _x_3 then _x_1 else List.tl _x_1 in let (_x_5 : int list) = if _x_3 then List.tl _x_2 else _x_2 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_4 in let (_x_7 : int list) = if _x_6 then _x_4 else List.tl _x_4 in let (_x_8 : int list) = if _x_6 then List.tl _x_5 else _x_5 in let (_x_9 : bool) = List.hd _x_8 <= List.hd _x_7 in merge (if _x_9 then _x_7 else (List.tl _x_7)) (if _x_9 then List.tl _x_8 else _x_8)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds x) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in let (_x_4 : int list) = if _x_3 then _x_1 else List.tl _x_1 in let (_x_5 : int list) = if _x_3 then List.tl _x_2 else _x_2 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_4 in merge (if _x_6 then _x_4 else (List.tl _x_4)) (if _x_6 then List.tl _x_5 else _x_5)
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds (List.tl x))) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl (odds (List.tl (odds x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds x)) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds (List.tl (odds x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds x)))) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds (List.tl (odds (List.tl x)))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (odds x))))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (List.tl (List.tl (merge_sort x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (odds (odds x)))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds x))) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds (odds x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                      • odds (odds (odds (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl (odds x))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • 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 (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl (odds (List.tl x)))) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl (odds (odds x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (odds (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (odds (odds (odds (odds x))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds (List.tl x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds (odds (List.tl x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (odds (odds x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds (odds x)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl (odds (List.tl x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • 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 (odds x))))))))
                                                                                                                                                                                                                      • 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 (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds (odds (List.tl x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds (odds x))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (odds x)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds (List.tl x))) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (List.tl (odds x)) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (odds (List.tl (odds (List.tl x))))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds (odds (odds x))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • let (_x_0 : int list) = merge_sort (odds x) in let (_x_1 : int list) = merge_sort (odds (List.tl x)) in let (_x_2 : bool) = List.hd _x_1 <= List.hd _x_0 in let (_x_3 : int list) = if _x_2 then _x_0 else List.tl _x_0 in let (_x_4 : int list) = if _x_2 then List.tl _x_1 else _x_1 in let (_x_5 : bool) = List.hd _x_4 <= List.hd _x_3 in let (_x_6 : int list) = if _x_5 then _x_3 else List.tl _x_3 in let (_x_7 : int list) = if _x_5 then List.tl _x_4 else _x_4 in let (_x_8 : bool) = List.hd _x_7 <= List.hd _x_6 in merge (if _x_8 then _x_6 else (List.tl _x_6)) (if _x_8 then List.tl _x_7 else _x_7)
                                                                                                                                                                                                                      • let (_x_0 : int list) = odds (odds (List.tl x)) in let (_x_1 : int list) = merge_sort (odds _x_0) in let (_x_2 : int list) = merge_sort (odds (List.tl _x_0)) in let (_x_3 : bool) = List.hd _x_2 <= List.hd _x_1 in merge (if _x_3 then _x_1 else (List.tl _x_1)) (if _x_3 then List.tl _x_2 else _x_2)
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds (odds (odds x)))))))
                                                                                                                                                                                                                      proof attempt
                                                                                                                                                                                                                      ground_instances100
                                                                                                                                                                                                                      definitions0
                                                                                                                                                                                                                      inductions0
                                                                                                                                                                                                                      search_time
                                                                                                                                                                                                                      1.610s
                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                      • start[1.610s] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (merge_sort_37 x_50)
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (is_sorted_41 (merge_sort_37 x_50))
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (odds_2562 (|get.::.1_2561| x_50))
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 (|get.::.1_2561| x_50)))
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (odds_2562 x_50)
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (merge_sort_37 (odds_2562 x_50))
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (merge_14 (merge_sort_37 (odds_2562 x_50))
                                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 (|get.::.1_2561| x_50…
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (odds_2562 (|get.::.1_2561| (|get.::.1_2561| x_50)))
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (odds_2562 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| x_50))))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (is_sorted_41 (|get.::.1_2561| (merge_sort_37 x_50)))
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (odds_2562 (|get.::.1_2561| (odds_2562 x_50)))
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (odds_2562 (odds_2562 x_50))
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (merge_sort_37 (odds_2562 (odds_2562 x_50)))
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (let ((a!1 (merge_sort_37 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                        (merge_14 (merge_sort_…
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                          (merge_sort_37 a!1))
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (odds_2562 (odds_2562 (|get.::.1_2561| x_50)))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (let ((a!1 (merge_sort_37 (odds_2562 (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                  (a!2 (odds_2562 (|g…
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.0_2560| (merge_sort_37 (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                      (a!4 (|get.::…
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (odds_2562 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 x_50))))
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                      (odds_25…
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                        (odds_2562 a!1…
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                          (odds_25…
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                            (odds_2562 a!1))
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                              (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                  (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (is_sorted_41 (|get.::.1_2561| (|get.::.1_2561| (merge_sort_37 x_50))))
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                          (a!2 (|get.::.1_2561| (…
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                          (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (odds_2562 (odds_2562 (odds_2562 x_50)))
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (merge_sort_37 (odds_2562 (odds_2562 (odds_2562 x_50))))
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (let ((a!1 (merge_sort_37 (odds_2562 (odds_2562 (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                                    (a!2 (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (let ((a!1 (merge_sort_37 (odds_2562 (|get.::.1_2561| (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.0_256…
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                    (odds_2562 a!1…
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                      (odds_2562 (|g…
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                        (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                            (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                (merge_14 (merge_sor…
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                                                                      (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                    (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                          (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                                                                                (a!2 (|get.::.1_2561| (…
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_2560| (merge_sort_37 (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                                                                                  (a!3 (|get.::…
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                (odds_2562 (|g…
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                  (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (merge_sort_37 x_50))))))
                                                                                                                                                                                                                                                                                                                                    (is_sorted…
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                      (odds_25…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                        (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                          (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                            (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                (odds_2562 (|g…
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                  (odds_2562 (|get.::.1_2561…
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (odds_2562 (odds_2562 (odds_2562 (odds_2562 x_50))))
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                                                                                          (a!2 (merge_sort_37 (od…
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                          (odds_25…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                            (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                    (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                          (a!2 (|get.::.1_2561| (odds_2…
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (merge_sort_37 (odds_2562 (|get.::.1_2561| (odds_2562 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                            (a!2 (|get.::.0_256…
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                          (odds_2562 (|g…
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                            (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                              (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                    (odds_2562 (odds_256…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                      (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                            (odds_2562 (odds_256…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2561| (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                (odds_2562 (|g…
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (|get.::.1_2561| (odds_2562 (|get.::.1_2561| x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                                          (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                        (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                            (odds_2562 (|get.::.1_2561…
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                              (odds_2562 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2561| (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                  (odds_2562 (odds_256…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                    (odds_2562 (|get.::.1_2561…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (odds_2562 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_37 (odds_2562 …
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_2562 (odds_2562 (odds_2562 (|get.::.1_2561| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_2562 (odds_2562 (|get.::.1_2561| (odds_2562 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                (odds_2562 a!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.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                      && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                              and merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definition of merge_sort to:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1':
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              We can eliminate destructors by the following substitution:
                                                                                                                                                                                                                                                                                                                                                                                                                               x -> x1 :: x2
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1'':
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted (merge_sort (odds (x1 :: x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted (merge_sort (odds x2))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge (merge_sort (odds (x1 :: x2))) (merge_sort (odds x2)))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Candidates for generalization:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               odds (x1 :: x2)
                                                                                                                                                                                                                                                                                                                                                                                                                               odds x2
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1''':
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted (merge_sort gen_1)
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted (merge_sort gen_2)
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge (merge_sort gen_1) (merge_sort gen_2))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Candidates for generalization:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               merge_sort gen_1
                                                                                                                                                                                                                                                                                                                                                                                                                               merge_sort gen_2
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This produces the modified subgoal:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1'''':
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted gen_3
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge gen_3 gen_4)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Must try induction.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               Aborting proof attempt for merge_sort_sorts.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:induct merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Checkpoints:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted gen_3
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x2 <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge gen_3 gen_4)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Error[/server]: Maximum induction depth reached (1). You can set this with #max_induct.
                                                                                                                                                                                                                                                                                                                                                                                                                              

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

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                              In [23]:
                                                                                                                                                                                                                                                                                                                                                                                                                              #max_induct 2;;
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              theorem merge_sorts x y =
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted x && is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               ==>
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                              [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Out[23]:
                                                                                                                                                                                                                                                                                                                                                                                                                              val merge_sorts : int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                              Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              is_sorted x && is_sorted y ==> is_sorted (merge x y).
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (y = []) && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (y = []) && List.hd x < List.hd y && φ (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ x y).
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                              and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted x && is_sorted (List.tl y) ==> is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                              following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                              and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. (List.tl y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. List.hd y <= List.hd (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H7. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H8. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But we verify Subgoal 2.2 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. (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:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted (List.tl x) && is_sorted y ==> is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                              following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                               C2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definitions of is_sorted
                                                                                                                                                                                                                                                                                                                                                                                                                              and merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                               H7. List.hd x <= List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But we verify Subgoal 1.2 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               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.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Proved
                                                                                                                                                                                                                                                                                                                                                                                                                              proof
                                                                                                                                                                                                                                                                                                                                                                                                                              ground_instances5
                                                                                                                                                                                                                                                                                                                                                                                                                              definitions31
                                                                                                                                                                                                                                                                                                                                                                                                                              inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                              search_time
                                                                                                                                                                                                                                                                                                                                                                                                                              2.108s
                                                                                                                                                                                                                                                                                                                                                                                                                              details
                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                              smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                              num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-assume-eqs2
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-make-feasible21
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-max-columns18
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                              rlimit count242173
                                                                                                                                                                                                                                                                                                                                                                                                                              mk clause153
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype occurs check47
                                                                                                                                                                                                                                                                                                                                                                                                                              mk bool var186
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-lower9
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-diseq2
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype splits15
                                                                                                                                                                                                                                                                                                                                                                                                                              decisions61
                                                                                                                                                                                                                                                                                                                                                                                                                              propagations161
                                                                                                                                                                                                                                                                                                                                                                                                                              interface eqs2
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-max-rows8
                                                                                                                                                                                                                                                                                                                                                                                                                              conflicts20
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype accessor ax10
                                                                                                                                                                                                                                                                                                                                                                                                                              minimized lits5
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype constructor ax17
                                                                                                                                                                                                                                                                                                                                                                                                                              final checks11
                                                                                                                                                                                                                                                                                                                                                                                                                              added eqs255
                                                                                                                                                                                                                                                                                                                                                                                                                              del clause100
                                                                                                                                                                                                                                                                                                                                                                                                                              arith eq adapter8
                                                                                                                                                                                                                                                                                                                                                                                                                              arith-upper13
                                                                                                                                                                                                                                                                                                                                                                                                                              memory135.070000
                                                                                                                                                                                                                                                                                                                                                                                                                              max memory152.870000
                                                                                                                                                                                                                                                                                                                                                                                                                              num allocs53601769751.000000
                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                              • start[2.108s, "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.108s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                    (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                  :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                             && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (y = []) && List.hd x < List.hd y && φ (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                • Split (let (_x_0 : bool) = is_sorted x in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_1 : bool) = is_sorted y in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_2 : bool) = is_sorted (merge x y) || not (_x_0 && _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_3 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_4 : bool) = not _x_3 in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_5 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_6 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_7 : bool) = _x_6 && _x_5 in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_8 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_9 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                         ((_x_2
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not
                                                                                                                                                                                                                                                                                                                                                                                                                                              (not ((_x_4 && _x_5) && _x_6) && not ((_x_3 && _x_5) && _x_6)))
                                                                                                                                                                                                                                                                                                                                                                                                                                          && (_x_2
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                 ((_x_7 && _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (is_sorted (merge x _x_8) || not (_x_0 && is_sorted _x_8)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                         && (_x_2
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                ((_x_7 && _x_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (is_sorted (merge _x_9 y) || not (is_sorted _x_9 && _x_1))))
                                                                                                                                                                                                                                                                                                                                                                                                                                         :cases [let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_1 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((not (is_sorted x) || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || (not _x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || (_x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_0 : bool) = is_sorted x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_1 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((((not _x_0 || not (is_sorted y)) || x = []) || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (_x_0 && is_sorted _x_1 ==> is_sorted (merge x _x_1)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_0 : bool) = is_sorted y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((((not (is_sorted x) || not _x_0) || x = []) || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted _x_1 && _x_0 ==> is_sorted (merge _x_1 y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y)])
                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_0 : bool) = is_sorted y in let (_x_1 : int list) = List.tl x in (((((not (is_sorted x) || not _x_0) || x = []) || y = []) || List.hd y <= List.hd x) || not (is_sorted _x_1 && _x_0 ==> is_sorted (merge _x_1 y))) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[2.098s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : bool) = is_sorted y in
                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                        (((((not (is_sorted x) || not _x_0) || x = []) || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                          || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (is_sorted _x_1 && _x_0 ==> is_sorted (merge _x_1 y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_2 : int list) = merge _x_1 y in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_3 : bool) = is_sorted _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_4 : bool) = is_sorted _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_5 : int) = List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_6 : bool) = List.hd y <= _x_5 in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_7 : bool) = not (is_sorted y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_8 : bool) = _x_2 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_9 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_10 : bool) = not _x_9 in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_11 : bool)
                                                                                                                                                                                                                                                                                                                                                                                                                                          = ((((y = [] || _x_0) || _x_6) || _x_7) || _x_8) || not _x_3
                                                                                                                                                                                                                                                                                                                                                                                                                                      in
                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_12 : bool) = _x_5 <= List.hd _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                      (((((((_x_0 || _x_3) || _x_4) || _x_6) || _x_7) || _x_8) || _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                       && ((((_x_11 || _x_9) || not _x_4) || not (_x_5 <= List.hd _x_1)) || _x_12))
                                                                                                                                                                                                                                                                                                                                                                                                                                      && ((_x_11 || _x_10) || _x_12)
                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                      [is_sorted, merge, is_sorted, merge, is_sorted, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                      • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : bool) = is_sorted x in let (_x_1 : int list) = List.tl y in (((((not _x_0 || not (is_sorted y)) || x = []) || y = []) || not (List.hd y <= List.hd x)) || not (_x_0 && is_sorted _x_1 ==> is_sorted (merge x _x_1))) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[2.098s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_0 : bool) = is_sorted x in
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_1 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                            (((((not _x_0 || not (is_sorted y)) || x = []) || y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (_x_0 && is_sorted _x_1 ==> is_sorted (merge x _x_1)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                          into
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : bool) = y = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_1 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_2 : int list) = merge x _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_3 : bool) = is_sorted _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_4 : bool) = is_sorted _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_5 : int) = List.hd y in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_6 : bool) = not (_x_5 <= List.hd x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_7 : bool) = not (is_sorted x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_8 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_9 : bool) = not _x_8 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_10 : bool) = _x_2 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_11 : bool) = ((_x_0 || x = []) || _x_6) || _x_7 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_12 : bool) = not _x_3 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_13 : bool) = _x_5 <= List.hd _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                          (((((((_x_0 || _x_3) || _x_4) || _x_6) || _x_7) || _x_9) || _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                           && ((((((_x_11 || _x_8) || _x_12) || not (_x_5 <= List.hd _x_1)) || not _x_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                                || _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                               || _x_13))
                                                                                                                                                                                                                                                                                                                                                                                                                                          && ((((_x_11 || _x_12) || _x_9) || _x_10) || _x_13)
                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                          [is_sorted, merge, is_sorted, merge, is_sorted, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                          rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_0 : bool) = List.hd y <= List.hd x in let (_x_1 : bool) = not (y = []) in let (_x_2 : bool) = not (x = []) in (((not (is_sorted x) || not (is_sorted y)) || (not _x_0 && _x_1) && _x_2) || (_x_0 && _x_1) && _x_2) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[2.098s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_1 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                (((not (is_sorted x) || not (is_sorted y)) || (not _x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || (_x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                              true
                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                              [merge, is_sorted, merge, is_sorted, merge, is_sorted, merge, is_sorted]
                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                            is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[0.863s, "1"] is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                              :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                             && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • Split (let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_1 : bool) = not (x <> [] && _x_0 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_3 : bool) = is_sorted (merge_sort x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                     (_x_1 && _x_2 || _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (_x_3
                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((_x_2 && _x_1) && is_sorted (merge_sort (odds _x_0)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                             && is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     :cases [not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                             (((x = [] || x <> [] && _x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted (merge_sort (odds _x_0))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : int list) = List.tl x in (((x = [] || x <> [] && _x_0 = []) || not (is_sorted (merge_sort (odds _x_0)))) || not (is_sorted (merge_sort (odds x)))) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[0.862s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((x = [] || x <> [] && _x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || not (is_sorted (merge_sort (odds _x_0))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not (is_sorted (merge_sort (odds x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                  into
                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_1 : int list) = merge_sort (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_2 : int list) = merge_sort (odds x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((_x_0 = [] || x = []) || not (is_sorted _x_1)) || not (is_sorted _x_2))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || is_sorted (merge _x_2 _x_1)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                  merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                  rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                    forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                      true
                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                      []
                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                      merge_sorts
                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                      not (x <> [] && List.tl x = []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.862s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                          not (x <> [] && List.tl x = []) && not (x = []) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                        true
                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                        [is_sorted, merge_sort, is_sorted, merge_sort, is_sorted, merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Merge Sort contains the right elements

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    What does this mean, and why does it matter?

                                                                                                                                                                                                                                                                                                                                                                                                                                                    An incorrect sorting function

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Multiset equivalence

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Termination proof

                                                                                                                                                                                                                                                                                                                                                                                                                                                    call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                    originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                    subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    path[y <> [] && List.hd y = x && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                    0.014s
                                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-make-feasible16
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-columns13
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count4882
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-cheap-eqs5
                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause30
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check32
                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var90
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-lower13
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions26
                                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations47
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-rows5
                                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax12
                                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs76
                                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter10
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-upper10
                                                                                                                                                                                                                                                                                                                                                                                                                                                    memory108.770000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory152.870000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs62002050777.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.014s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int) = Ordinal.count y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_2 : int) = Ordinal.count _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_3 : bool) = _x_1 <> [] && List.hd _x_1 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_4 : bool) = not (_x_1 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (y <> [] && List.hd y = x) && not (y = []) && _x_0 >= 0 && _x_2 >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> not (_x_3 && _x_4) && not (not _x_3 && _x_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || Ordinal.( << ) (Ordinal.Int _x_2) (Ordinal.Int _x_0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_1 : int) = Ordinal.count _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_2 : int) = Ordinal.count y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_3 : bool) = _x_0 <> [] && List.hd _x_0 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_4 : bool) = not (_x_0 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      (Ordinal.( << ) (Ordinal.Int _x_1) (Ordinal.Int _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (_x_3 && _x_4) && not (not _x_3 && _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                         ((((y <> [] && List.hd y = x) && not (y = [])) && _x_2 >= 0) && _x_1 >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                      []
                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|count_`ty_0 list`_5850| y_5838)
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|count_`ty_0 list`_5850| (|get.::.1_5828| y_5838))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                              (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_5850|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    …
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • Unsat

                                                                                                                                                                                                                                                                                                                                                                                                                                                              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.013s
                                                                                                                                                                                                                                                                                                                                                                                                                                                              details
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                              smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                              num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-make-feasible11
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-max-columns12
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                              rlimit count2345
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-cheap-eqs2
                                                                                                                                                                                                                                                                                                                                                                                                                                                              mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype occurs check29
                                                                                                                                                                                                                                                                                                                                                                                                                                                              mk bool var58
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-lower7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              decisions21
                                                                                                                                                                                                                                                                                                                                                                                                                                                              propagations33
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-max-rows4
                                                                                                                                                                                                                                                                                                                                                                                                                                                              conflicts9
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype accessor ax5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype constructor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                              final checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              added eqs43
                                                                                                                                                                                                                                                                                                                                                                                                                                                              del clause5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith-upper5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              memory106.230000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              max memory152.870000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              num allocs61762401001.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.013s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : int) = Ordinal.count y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_1 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_2 : int) = Ordinal.count _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_3 : bool) = _x_1 <> [] && List.hd _x_1 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_4 : bool) = not (_x_1 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  not (y <> [] && List.hd y = x) && not (y = []) && _x_0 >= 0 && _x_2 >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> not (_x_3 && _x_4) && not (not _x_3 && _x_4)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || Ordinal.( << ) (Ordinal.Int _x_2) (Ordinal.Int _x_0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_1 : int) = Ordinal.count _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_2 : int) = Ordinal.count y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_3 : bool) = _x_0 <> [] && List.hd _x_0 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_4 : bool) = not (_x_0 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                (Ordinal.( << ) (Ordinal.Int _x_1) (Ordinal.Int _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (_x_3 && _x_4) && not (not _x_3 && _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((not (y <> [] && List.hd y = x) && not (y = [])) && _x_2 >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && _x_1 >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|count_`ty_0 list`_5850| y_5838)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (|count_`ty_0 list`_5850| (|get.::.1_5828| y_5838))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_5850|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • Unsat

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        In [26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        theorem num_occur_merge a x y =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Out[26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        val num_occur_merge : int -> int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs a (merge x y) = num_occurs a x + num_occurs a y.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             && not (y = []) && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (y = []) && List.hd x < List.hd y && φ a (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ a x y).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a x + num_occurs a (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (List.tl x) + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        definitions14
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        0.293s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[0.293s, "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.293s, "1"] num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (y = []) && List.hd x < List.hd y && φ a (List.tl x) y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Split (let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_1 : bool) = not _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_2 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_3 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_4 : int) = num_occurs a x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_5 : int) = num_occurs a y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_6 : bool) = num_occurs a (merge x y) = _x_4 + _x_5 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_7 : bool) = _x_3 && _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_8 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_9 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ((not (not ((_x_1 && _x_2) && _x_3) && not ((_x_0 && _x_2) && _x_3))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || _x_6)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((_x_7 && _x_0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && num_occurs a (merge x _x_8) = _x_4 + num_occurs a _x_8)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || _x_6))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ((_x_7 && _x_1)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && num_occurs a (merge _x_9 y) = num_occurs a _x_9 + _x_5)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || _x_6)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   :cases [let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_1 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ((not _x_0 && _x_1) && _x_2 || (_x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_0 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_1 : int) = num_occurs a x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (num_occurs a (merge x _x_0) = _x_1 + num_occurs a _x_0))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = _x_1 + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_1 : int) = num_occurs a y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (num_occurs a (merge _x_0 y) = num_occurs a _x_0 + _x_1))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = num_occurs a x + _x_1])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_0 : int list) = List.tl x in let (_x_1 : int) = num_occurs a y in (((x = [] || y = []) || List.hd y <= List.hd x) || not (num_occurs a (merge _x_0 y) = num_occurs a _x_0 + _x_1)) || num_occurs a (merge x y) = num_occurs a x + _x_1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.292s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_1 : int) = num_occurs a y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (num_occurs a (merge _x_0 y) = num_occurs a _x_0 + _x_1))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || num_occurs a (merge x y) = num_occurs a x + _x_1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : int list) = List.tl y in let (_x_1 : int) = num_occurs a x in (((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (num_occurs a (merge x _x_0) = _x_1 + num_occurs a _x_0)) || num_occurs a (merge x y) = _x_1 + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.292s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_1 : int) = num_occurs a x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not (num_occurs a (merge x _x_0) = _x_1 + num_occurs a _x_0))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (merge x y) = _x_1 + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : bool) = List.hd y <= List.hd x in let (_x_1 : bool) = not (y = []) in let (_x_2 : bool) = not (x = []) in ((not _x_0 && _x_1) && _x_2 || (_x_0 && _x_1) && _x_2) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.292s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_1 : bool) = not (y = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ((not _x_0 && _x_1) && _x_2 || (_x_0 && _x_1) && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [num_occurs, merge, num_occurs, merge, num_occurs, merge, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    In [27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem num_occurs_arith (x : int list) (a : int) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a x - num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@induct functional num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Out[27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    val num_occurs_arith : int list -> int -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> num_occurs a (odds (List.tl x)) = num_occurs a x - num_occurs a (odds x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    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 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not (not (x <> [] && List.hd x = a) && not (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 (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not (x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     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.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     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.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. 0 =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.2':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. 0 = num_occurs a (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 x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 1 =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.1':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 0 = num_occurs (List.hd (List.tl x)) (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    following 4 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. 0 =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 0 = num_occurs (List.hd x) (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 x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     1 =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0 = num_occurs (List.hd x) (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def odds)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:induct num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions48
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1.196s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.196s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int list) = List.tl :var_0: in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        not (:var_0: = []) && not (_x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> num_occurs :var_1: (odds _x_0) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs :var_1: :var_0: - num_occurs :var_1: (odds :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : int list) = List.tl x in (x = [] || _x_0 = []) || num_occurs a (odds _x_0) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[1.196s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (x = [] || _x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a (odds _x_0) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • induction on (functional num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        :scheme (not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (not (x <> [] && List.hd x = a) && not (x = [])) ==> 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (x <> [] && List.hd x = a) && φ a (List.tl x) ==> 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not (x = []) && (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • Split (let (_x_0 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_2 : bool) = not (_x_1 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_3 : int) = num_occurs a (odds _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_4 : bool)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   = not (_x_0 && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || _x_3 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_5 : bool) = x <> [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_6 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_7 : bool) = _x_5 && _x_6 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_8 : bool) = not _x_7 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_9 : int list) = List.tl _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_10 : bool)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   = not (_x_2 && not (_x_9 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || num_occurs a (odds _x_9) = num_occurs a _x_1 + -1 * _x_3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               ((_x_4 || not (not (_x_7 && _x_0) && not (_x_8 && _x_0)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && (_x_4 || not ((_x_0 && _x_8) && _x_10)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (_x_4 || not (((_x_0 && _x_5) && _x_6) && _x_10))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               :cases [let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_2 : bool) = x <> [] && List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_3 : bool) = not _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((_x_0 || _x_1 = []) || _x_2 && _x_3) || not _x_2 && _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (odds _x_1) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_2 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_3 : int list) = List.tl _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_4 : int) = num_occurs a (odds _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ((((_x_0 || _x_2) || _x_0) || x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (not _x_2 && not (_x_3 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> num_occurs a (odds _x_3) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a _x_1 + -1 * _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || _x_4 = num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_2 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_3 : int list) = List.tl _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_4 : int) = num_occurs a (odds _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((((_x_0 || _x_2) || _x_0) || not (x <> []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (not _x_2 && not (_x_3 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> num_occurs a (odds _x_3) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a _x_1 + -1 * _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || _x_4 = num_occurs a x + -1 * num_occurs a (odds x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : bool) = x = [] in let (_x_1 : int list) = List.tl x in let (_x_2 : bool) = _x_1 = [] in let (_x_3 : int list) = List.tl _x_1 in let (_x_4 : int) = num_occurs a (odds _x_1) in (((((_x_0 || _x_2) || _x_0) || not (x <> [])) || not (List.hd x = a)) || not (not _x_2 && not (_x_3 = []) ==> num_occurs a (odds _x_3) = num_occurs a _x_1 + -1 * _x_4)) || _x_4 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[1.195s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_2 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_3 : int list) = List.tl _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_4 : int) = num_occurs a (odds _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((((_x_0 || _x_2) || _x_0) || not (x <> [])) || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (not _x_2 && not (_x_3 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> num_occurs a (odds _x_3) = num_occurs a _x_1 + -1 * _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || _x_4 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_1 : bool) = x = [] || _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_3 : bool) = _x_2 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_4 : int) = List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_5 : int) = num_occurs _x_4 (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_6 : int) = num_occurs _x_4 (odds _x_2) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_7 : int) = num_occurs _x_4 _x_0 + -1 * _x_6 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_8 : bool) = (_x_1 || _x_3) || _x_5 = _x_7 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_9 : int) = num_occurs _x_4 _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_10 : int) = -1 * _x_5 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_11 : bool) = List.hd _x_0 = _x_4 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_12 : bool) = not _x_11 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_13 : bool) = _x_1 || not _x_3 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((_x_8 || not (_x_6 = _x_9 + _x_10)) || _x_11)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && ((_x_8 || _x_12) || not (_x_6 = 1 + _x_9 + _x_10)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             && ((_x_13 || 0 = _x_7) || _x_11))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && ((_x_13 || 1 = _x_7) || _x_12)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            [num_occurs, odds, num_occurs, num_occurs, num_occurs, num_occurs, odds,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs, odds, num_occurs, num_occurs, odds, num_occurs, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_0 : bool) = x = [] in let (_x_1 : int list) = List.tl x in let (_x_2 : bool) = _x_1 = [] in let (_x_3 : int list) = List.tl _x_1 in let (_x_4 : int) = num_occurs a (odds _x_1) in ((((_x_0 || _x_2) || _x_0) || x <> [] && List.hd x = a) || not (not _x_2 && not (_x_3 = []) ==> num_occurs a (odds _x_3) = num_occurs a _x_1 + -1 * _x_4)) || _x_4 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[1.195s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_2 : bool) = _x_1 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_3 : int list) = List.tl _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_4 : int) = num_occurs a (odds _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ((((_x_0 || _x_2) || _x_0) || x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (not _x_2 && not (_x_3 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       ==> num_occurs a (odds _x_3) = num_occurs a _x_1 + -1 * _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || _x_4 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_1 : bool) = (List.hd x = a || x = []) || _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_3 : bool) = _x_2 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_4 : bool) = _x_1 || _x_3 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_5 : int) = num_occurs a (odds _x_2) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_6 : int) = num_occurs a _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_7 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_8 : int) = -1 * _x_7 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_9 : bool) = List.hd _x_0 = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_10 : int) = num_occurs a _x_0 + -1 * _x_5 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_11 : bool) = _x_7 = _x_10 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_12 : bool) = not _x_9 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_13 : bool) = _x_1 || not _x_3 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((((_x_4 || not (_x_5 = _x_6 + _x_8)) || _x_9) || _x_11)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (((_x_4 || _x_12) || _x_11) || not (_x_5 = 1 + _x_6 + _x_8)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && ((_x_13 || _x_9) || 0 = _x_10))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && ((_x_13 || _x_12) || 1 = _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [num_occurs, odds, num_occurs, num_occurs, num_occurs, num_occurs, odds,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs, odds, num_occurs, num_occurs, odds, num_occurs, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : bool) = x = [] in let (_x_1 : int list) = List.tl x in let (_x_2 : bool) = x <> [] && List.hd x = a in let (_x_3 : bool) = not _x_0 in (((_x_0 || _x_1 = []) || _x_2 && _x_3) || not _x_2 && _x_3) || num_occurs a (odds _x_1) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[1.195s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : bool) = x = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_1 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_2 : bool) = x <> [] && List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_3 : bool) = not _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((_x_0 || _x_1 = []) || _x_2 && _x_3) || not _x_2 && _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (odds _x_1) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                And now, our second main theorem at last:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                In [28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                theorem merge_sort_elements a (x : int list) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [@@induct functional merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Out[28]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                val merge_sort_elements : int -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x = num_occurs a (merge_sort x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                We shall induct according to a scheme derived from merge_sort.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && φ a (odds (List.tl x)) && φ a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C1. num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                But simplification reduces this to true, using the definitions of merge_sort
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                and num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                This simplifies, using the definitions of merge_sort and num_occurs, and the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite rule num_occurs_arith to the following 2 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 C1. num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H2. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H3. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 H4. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     -1 + num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 num_occurs a (List.tl x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 -1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 + num_occurs a (merge (merge_sort (odds x)) (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                But simplification reduces this to true, using the rewrite rule
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occur_merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:def merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:rw num_occur_merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:rw num_occurs_arith)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (:induct merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                definitions16
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                11.927s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[11.927s, "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[11.927s, "1"] num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (x <> [] && List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && φ a (odds (List.tl x)) && φ a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • Split (let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_1 : bool) = not (x <> [] && _x_0 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_2 : bool) = not (x = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_3 : bool) = num_occurs a x = num_occurs a (merge_sort x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_4 : int list) = odds _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_5 : int list) = odds x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (_x_1 && _x_2 || _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (((_x_2 && _x_1)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && num_occurs a _x_4 = num_occurs a (merge_sort _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && num_occurs a _x_5 = num_occurs a (merge_sort _x_5))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               || _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           :cases [not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a x = num_occurs a (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_1 : int list) = odds _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_2 : int list) = odds x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((x = [] || x <> [] && _x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not (num_occurs a _x_1 = num_occurs a (merge_sort _x_1)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not (num_occurs a _x_2 = num_occurs a (merge_sort _x_2)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || num_occurs a x = num_occurs a (merge_sort x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : int list) = List.tl x in let (_x_1 : int list) = odds _x_0 in let (_x_2 : int list) = odds x in (((x = [] || x <> [] && _x_0 = []) || not (num_occurs a _x_1 = num_occurs a (merge_sort _x_1))) || not (num_occurs a _x_2 = num_occurs a (merge_sort _x_2))) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[11.926s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_1 : int list) = odds _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_2 : int list) = odds x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((x = [] || x <> [] && _x_0 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (num_occurs a _x_1 = num_occurs a (merge_sort _x_1)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (num_occurs a _x_2 = num_occurs a (merge_sort _x_2)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : int list) = odds x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_2 : int) = num_occurs a _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_3 : int list) = merge_sort _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_4 : bool) = (_x_0 = [] || x = []) || not (_x_2 = num_occurs a _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_5 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_6 : int) = num_occurs a _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_7 : int) = _x_6 + -1 * _x_2 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_8 : int list) = merge_sort (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_9 : int) = num_occurs a _x_8 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_10 : int) = num_occurs a (merge _x_3 _x_8) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((_x_4 || _x_5) || not (_x_7 = _x_9)) || _x_6 = _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && (((_x_4 || not _x_5) || _x_6 = -1 + _x_10) || not (_x_7 = -1 + _x_9))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [merge_sort, num_occurs, merge_sort, num_occurs, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs_arith
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        not (x <> [] && List.tl x = []) && not (x = []) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[11.926s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            not (x <> [] && List.tl x = []) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          [num_occurs, merge_sort, num_occurs, num_occurs, merge_sort, num_occurs,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs, num_occurs, num_occurs, merge_sort, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Merge Sort is Correct!

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      To recap, we've proved:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      theorem merge_sort_sorts x =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      and

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Beautiful! Happy proving (and sorting)!