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 (_cnt l); Ordinal.Int (_cnt m)]
sub ordinalOrdinal.of_list [Ordinal.Int (_cnt (List.tl l)); Ordinal.Int (_cnt m)]
path[List.hd l < List.hd m && not Is_a([], m) && not Is_a([], l)]
proof
detailed proof
ground_instances8
definitions0
inductions0
search_time
0.024s
details
Expand
smt_stats
num checks18
arith-assume-eqs5
arith-make-feasible122
arith-max-columns39
arith-conflicts7
rlimit count33341
arith-cheap-eqs4
mk clause180
datatype occurs check175
mk bool var397
arith-lower86
arith-diseq36
datatype splits21
decisions165
arith-propagations25
propagations275
interface eqs4
arith-bound-propagations-cheap25
arith-max-rows16
conflicts27
datatype accessor ax50
minimized lits6
arith-bound-propagations-lp6
datatype constructor ax44
num allocs2855216
final checks21
added eqs462
del clause96
arith eq adapter76
arith-upper137
time0.001000
memory8.580000
max memory8.580000
Expand
  • start[0.024s]
      let (_x_0 : int) = List.hd m in
      let (_x_1 : bool) = not Is_a([], m) in
      let (_x_2 : bool) = count.list mk_nat m >= 0 in
      let (_x_3 : int list) = List.tl l in
      let (_x_4 : bool) = List.hd _x_3 < _x_0 in
      let (_x_5 : bool) = _x_1 && not Is_a([], _x_3) in
      List.hd l < _x_0
      && _x_1
         && not Is_a([], l)
            && count.list mk_nat l >= 0
               && _x_2 && count.list mk_nat _x_3 >= 0 && _x_2
      ==> not (_x_4 && _x_5) && not (not _x_4 && _x_5)
          || Ordinal.( << ) (if Is_a([], …) then … else …)
             (if Is_a([], …) 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 Is_a([], m) in
    let (_x_4 : bool) = not Is_a([], _x_1) in
    let (_x_5 : int) = count.list mk_nat _x_1 in
    let (_x_6 : Ordinal.t) = Ordinal.Int 1 in
    let (_x_7 : int) = count.list mk_nat m in
    let (_x_8 : Ordinal.t) = Ordinal.Int _x_7 in
    let (_x_9 : int) = count.list mk_nat 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 Is_a([], l)) && _x_9 >= 0)
         && _x_7 >= 0)
        && _x_5 >= 0)
    expansions
    []
    rewrite_steps
      forward_chaining
      • unroll
        expr
        (|`count.list mk_nat[0]`_1694| l_1679)
        expansions
        • unroll
          expr
          (|Ordinal.shift_205|
            (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| l_1679))
            (|Ordinal.Int_11…
          expansions
          • unroll
            expr
            (|Ordinal.plus_167|
              (|Ordinal.shift_205|
                (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| l_1…
            expansions
            • unroll
              expr
              (|`count.list mk_nat[0]`_1694| m_1680)
              expansions
              • unroll
                expr
                (|`count.list mk_nat[0]`_1694| (|get.::.1_1678| l_1679))
                expansions
                • unroll
                  expr
                  (|Ordinal.shift_205|
                    (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| (|get.::.1_1678| l_1679)))
                  …
                  expansions
                  • unroll
                    expr
                    (let ((a!1 (|Ordinal.shift_205|
                                 (|Ordinal.Int_111|
                                   (|`count.list mk_nat[…
                    expansions
                    • unroll
                      expr
                      (let ((a!1 (|Ordinal.shift_205|
                                   (|Ordinal.Int_111|
                                     (|`count.list mk_nat[…
                      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 (_cnt l); Ordinal.Int (_cnt m)]
                      sub ordinalOrdinal.of_list [Ordinal.Int (_cnt l); Ordinal.Int (_cnt (List.tl m))]
                      path[not (List.hd l < List.hd m) && not Is_a([], m) && not Is_a([], l)]
                      proof
                      detailed proof
                      ground_instances13
                      definitions0
                      inductions0
                      search_time
                      0.040s
                      details
                      Expand
                      smt_stats
                      num checks27
                      arith-assume-eqs15
                      arith-make-feasible340
                      arith-max-columns81
                      arith-conflicts12
                      rlimit count23399
                      arith-cheap-eqs140
                      mk clause487
                      datatype occurs check613
                      mk bool var1077
                      arith-lower283
                      arith-diseq61
                      datatype splits81
                      decisions519
                      arith-propagations61
                      propagations818
                      interface eqs15
                      arith-bound-propagations-cheap61
                      arith-max-rows42
                      conflicts49
                      datatype accessor ax123
                      minimized lits4
                      arith-bound-propagations-lp41
                      datatype constructor ax152
                      num allocs950500
                      final checks56
                      added eqs1227
                      del clause255
                      arith eq adapter222
                      arith-upper372
                      memory5.770000
                      max memory5.770000
                      Expand
                      • start[0.040s]
                          let (_x_0 : int) = List.hd l in
                          let (_x_1 : bool) = not Is_a([], l) in
                          let (_x_2 : bool) = count.list mk_nat l >= 0 in
                          let (_x_3 : int list) = List.tl m in
                          let (_x_4 : bool) = _x_0 < List.hd _x_3 in
                          let (_x_5 : bool) = not Is_a([], _x_3) && _x_1 in
                          not (_x_0 < List.hd m)
                          && not Is_a([], m)
                             && _x_1
                                && _x_2
                                   && count.list mk_nat m >= 0 && _x_2 && count.list mk_nat _x_3 >= 0
                          ==> not (_x_4 && _x_5) && not (not _x_4 && _x_5)
                              || Ordinal.( << ) (if Is_a([], …) then … else …)
                                 (if Is_a([], …) 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 Is_a([], _x_0) in
                        let (_x_4 : bool) = not Is_a([], l) in
                        let (_x_5 : int) = count.list mk_nat l in
                        let (_x_6 : Ordinal.t) = Ordinal.shift (Ordinal.Int _x_5) (Ordinal.Int 1) in
                        let (_x_7 : int) = count.list mk_nat _x_0 in
                        let (_x_8 : int) = count.list mk_nat 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 Is_a([], m)) && _x_4) && _x_5 >= 0)
                             && _x_8 >= 0)
                            && _x_7 >= 0)
                        expansions
                        []
                        rewrite_steps
                          forward_chaining
                          • unroll
                            expr
                            (|`count.list mk_nat[0]`_1694| m_1680)
                            expansions
                            • unroll
                              expr
                              (|Ordinal.plus_167|
                                (|Ordinal.shift_205|
                                  (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| l_1…
                              expansions
                              • unroll
                                expr
                                (|`count.list mk_nat[0]`_1694| (|get.::.1_1678| m_1680))
                                expansions
                                • unroll
                                  expr
                                  (|`count.list mk_nat[0]`_1694| l_1679)
                                  expansions
                                  • unroll
                                    expr
                                    (|Ordinal.shift_205|
                                      (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| l_1679))
                                      (|Ordinal.Int_11…
                                    expansions
                                    • unroll
                                      expr
                                      (|Ordinal.plus_167|
                                        (|Ordinal.shift_205|
                                          (|Ordinal.Int_111| (|`count.list mk_nat[0]`_1694| l_1…
                                      expansions
                                      • unroll
                                        expr
                                        (let ((a!1 (|Ordinal.plus_167|
                                                     (|Ordinal.shift_205|
                                                       (|Ordinal.Int_111| (…
                                        expansions
                                        • unroll
                                          expr
                                          (|`count.list mk_nat[0]`_1694| (|get.::.1_1678| (|get.::.1_1678| m_1680)))
                                          expansions
                                          • unroll
                                            expr
                                            (|`count.list mk_nat[0]`_1694| (|get.::.1_1678| l_1679))
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|get.Ordinal.Cons.2_1685|
                                                           (|Ordinal.shift_205|
                                                             (|Ordinal.Int…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|get.Ordinal.Cons.2_1685|
                                                             (|Ordinal.shift_205|
                                                               (|Ordinal.Int…
                                                expansions
                                                • unroll
                                                  expr
                                                  (let ((a!1 (|Ordinal.plus_167|
                                                               (|Ordinal.shift_205|
                                                                 (|Ordinal.Int_111| (…
                                                  expansions
                                                  • unroll
                                                    expr
                                                    (let ((a!1 (|Ordinal.plus_167|
                                                                 (|Ordinal.shift_205|
                                                                   (|Ordinal.Int_111| (…
                                                    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 (_cnt l)
                                                    sub ordinalOrdinal.Int (_cnt (List.tl (List.tl l)))
                                                    path[not Is_a([], List.tl l) && not Is_a([], l)]
                                                    proof
                                                    detailed proof
                                                    ground_instances4
                                                    definitions0
                                                    inductions0
                                                    search_time
                                                    0.015s
                                                    details
                                                    Expand
                                                    smt_stats
                                                    num checks10
                                                    arith-assume-eqs2
                                                    arith-make-feasible26
                                                    arith-max-columns16
                                                    arith-conflicts2
                                                    rlimit count2526
                                                    arith-cheap-eqs10
                                                    mk clause32
                                                    datatype occurs check13
                                                    mk bool var80
                                                    arith-lower20
                                                    arith-diseq1
                                                    datatype splits1
                                                    decisions17
                                                    propagations26
                                                    interface eqs2
                                                    arith-max-rows5
                                                    conflicts8
                                                    datatype accessor ax10
                                                    arith-bound-propagations-lp1
                                                    datatype constructor ax8
                                                    num allocs8241621
                                                    final checks7
                                                    added eqs63
                                                    del clause26
                                                    arith eq adapter16
                                                    arith-upper16
                                                    memory8.740000
                                                    max memory8.740000
                                                    Expand
                                                    • start[0.015s]
                                                        let (_x_0 : ty_0 list) = List.tl l in
                                                        let (_x_1 : int) = count.list (const 0) l in
                                                        let (_x_2 : ty_0 list) = List.tl _x_0 in
                                                        let (_x_3 : int) = count.list (const 0) _x_2 in
                                                        not Is_a([], _x_0) && not Is_a([], l) && _x_1 >= 0 && _x_3 >= 0
                                                        ==> not (not Is_a([], List.tl _x_2) && not Is_a([], _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) = count.list (const 0) _x_1 in
                                                      let (_x_3 : int) = count.list (const 0) l in
                                                      (not (not Is_a([], List.tl _x_1) && not Is_a([], _x_1))
                                                       || Ordinal.( << ) (Ordinal.Int _x_2) (Ordinal.Int _x_3))
                                                      || not (((not Is_a([], _x_0) && not Is_a([], l)) && _x_3 >= 0) && _x_2 >= 0)
                                                      expansions
                                                      []
                                                      rewrite_steps
                                                        forward_chaining
                                                        • unroll
                                                          expr
                                                          (|`count.list (const 0)[0]`_1866| l_1855)
                                                          expansions
                                                          • unroll
                                                            expr
                                                            (|`count.list (const 0)[0]`_1866| (|get.::.1_1848| (|get.::.1_1848| l_1855)))
                                                            expansions
                                                            • unroll
                                                              expr
                                                              (let ((a!1 (|Ordinal.Int_111|
                                                                           (|`count.list (const 0)[0]`_1866|
                                                                             (|get.::…
                                                              expansions
                                                              • unroll
                                                                expr
                                                                (|`count.list (const 0)[0]`_1866| (|get.::.1_1848| l_1855))
                                                                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 Is_a([], List.tl l) and not Is_a([], 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 Is_a([], List.tl x) && not Is_a([], x)) ==> φ x)
                                                                 && (not Is_a([], x) && not Is_a([], 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 Is_a([], List.tl x) && not Is_a([], 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 Is_a([], x)
                                                                 H4. not Is_a([], 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.length (List.tl (List.tl x)) <=
                                                                     List.length (odds (List.tl (List.tl x)))
                                                                 H1. List.tl (List.tl x) = []
                                                                 H2. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                |---------------------------------------------------------------------------
                                                                 C0. Is_a([], List.tl x)
                                                                 C1. Is_a([], x)
                                                                
                                                                But simplification reduces this to true, using the definitions of List.length
                                                                and odds.
                                                                
                                                                Subgoal 1.2:
                                                                
                                                                 H0. List.length (List.tl (List.tl x)) <=
                                                                     List.length (odds (List.tl (List.tl x)))
                                                                 H1. (List.tl (List.tl x)) <> []
                                                                 H2. List.tl (List.tl (List.tl x)) = []
                                                                 H3. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                |---------------------------------------------------------------------------
                                                                 C0. Is_a([], List.tl x)
                                                                 C1. Is_a([], x)
                                                                
                                                                This simplifies, using the definitions of List.length and odds to:
                                                                
                                                                Subgoal 1.2':
                                                                
                                                                 H0. List.tl (List.tl (List.tl x)) = []
                                                                 H1. List.length (List.tl (List.tl (List.tl x))) <= 0
                                                                 H2. List.length (List.tl (List.tl x)) <= 0
                                                                 H3. (List.tl (List.tl x)) <> []
                                                                |---------------------------------------------------------------------------
                                                                 C0. Is_a([], List.tl x)
                                                                 C1. Is_a([], x)
                                                                
                                                                But simplification reduces this to true, using the definition of List.length.
                                                                
                                                                Subgoal 1.1:
                                                                
                                                                 H0. List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))
                                                                |---------------------------------------------------------------------------
                                                                 C0. Is_a([], List.tl x)
                                                                 C1. Is_a([], x)
                                                                 C2. 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
                                                                definitions22
                                                                inductions1
                                                                search_time
                                                                0.563s
                                                                Expand
                                                                • start[0.563s, "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.563s, "1"]
                                                                      (not (List.length x <= List.length (odds x)) || x = []) || List.tl x = []
                                                                  • induction on (functional odds)
                                                                    :scheme (not (not Is_a([], List.tl x) && not Is_a([], x)) ==> φ x)
                                                                            && (not Is_a([], x)
                                                                                && not Is_a([], 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) = not Is_a([], _x_0) in
                                                                           let (_x_2 : bool) = not Is_a([], x) in
                                                                           let (_x_3 : bool) = not (List.length x <= List.length (odds x)) in
                                                                           let (_x_4 : bool) = not (not (x = []) && not (_x_0 = [])) in
                                                                           let (_x_5 : sko_ty_0 list) = List.tl _x_0 in
                                                                           ((_x_1 && _x_2 || _x_3) || _x_4)
                                                                           && ((_x_3 || _x_4)
                                                                               || not
                                                                                  ((_x_2 && _x_1)
                                                                                   && (not (List.length _x_5 <= List.length (odds _x_5))
                                                                                       || not (not (_x_5 = []) && not (List.tl _x_5 = [])))))
                                                                           :cases [let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                                   ((not (List.length x <= List.length (odds x)) || x = [])
                                                                                    || _x_0 = [])
                                                                                   || not Is_a([], _x_0) && not Is_a([], x);
                                                                                   let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                                   let (_x_1 : sko_ty_0 list) = List.tl _x_0 in
                                                                                   ((((not (List.length x <= List.length (odds x)) || x = [])
                                                                                      || _x_0 = [])
                                                                                     || Is_a([], x))
                                                                                    || Is_a([], _x_0))
                                                                                   || not
                                                                                      (not (List.length _x_1 <= List.length (odds _x_1))
                                                                                       || not (not (_x_1 = []) && not (List.tl _x_1 = [])))])
                                                                    • subproof
                                                                      let (_x_0 : sko_ty_0 list) = List.tl x in let (_x_1 : sko_ty_0 list) = List.tl _x_0 in ((((not (List.length x <= List.length (odds x)) || x = []) || _x_0 = []) || Is_a([], x)) || Is_a([], _x_0)) || not (not (List.length _x_1 <= List.length (odds _x_1)) || not (not (_x_1 = []) && not (List.tl _x_1 = [])))
                                                                      • start[0.562s, "1"]
                                                                          let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                          let (_x_1 : sko_ty_0 list) = List.tl _x_0 in
                                                                          ((((not (List.length x <= List.length (odds x)) || x = []) || _x_0 = [])
                                                                            || Is_a([], x))
                                                                           || Is_a([], _x_0))
                                                                          || not
                                                                             (not (List.length _x_1 <= List.length (odds _x_1))
                                                                              || not (not (_x_1 = []) && not (List.tl _x_1 = [])))
                                                                      • simplify
                                                                        into
                                                                        let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                        let (_x_1 : bool) = Is_a([], _x_0) || Is_a([], 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
                                                                          • 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 : sko_ty_0 list) = List.tl x in ((not (List.length x <= List.length (odds x)) || x = []) || _x_0 = []) || not Is_a([], _x_0) && not Is_a([], x)
                                                                        • start[0.562s, "2"]
                                                                            let (_x_0 : sko_ty_0 list) = List.tl x in
                                                                            ((not (List.length x <= List.length (odds x)) || x = []) || _x_0 = [])
                                                                            || not Is_a([], _x_0) && not Is_a([], x)
                                                                        • simplify
                                                                          into
                                                                          true
                                                                          expansions
                                                                          []
                                                                          rewrite_steps
                                                                            forward_chaining
                                                                            • List.len_nonnegative
                                                                            • List.len_nonnegative

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

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

                                                                    Termination proof

                                                                    call `merge_sort (odds l)` from `merge_sort l`
                                                                    originalmerge_sort l
                                                                    submerge_sort (odds l)
                                                                    original ordinalmerge_sort_measure l
                                                                    sub ordinalmerge_sort_measure (odds l)
                                                                    path[not Is_a([], List.tl l) && not Is_a([], l)]
                                                                    proof
                                                                    detailed proof
                                                                    ground_instances3
                                                                    definitions0
                                                                    inductions0
                                                                    search_time
                                                                    0.013s
                                                                    details
                                                                    Expand
                                                                    smt_stats
                                                                    num checks8
                                                                    arith-make-feasible9
                                                                    arith-max-columns11
                                                                    rlimit count5232
                                                                    mk clause9
                                                                    datatype occurs check30
                                                                    mk bool var56
                                                                    arith-lower3
                                                                    datatype splits6
                                                                    decisions15
                                                                    propagations7
                                                                    arith-max-rows3
                                                                    conflicts6
                                                                    datatype accessor ax7
                                                                    datatype constructor ax10
                                                                    num allocs2628724096
                                                                    final checks6
                                                                    added eqs42
                                                                    del clause8
                                                                    arith eq adapter2
                                                                    arith-upper9
                                                                    memory38.520000
                                                                    max memory53.760000
                                                                    Expand
                                                                    • start[0.013s]
                                                                        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 Is_a([], List.tl _x_2) && not Is_a([], _x_2))
                                                                        in
                                                                        not Is_a([], List.tl l) && not Is_a([], 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 Is_a([], List.tl l) && not Is_a([], l))
                                                                       || not (not Is_a([], List.tl _x_0) && not Is_a([], _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_2276| l_2287)
                                                                          expansions
                                                                          • unroll
                                                                            expr
                                                                            (|List.length_2276| (odds_2281 l_2287))
                                                                            expansions
                                                                            • unroll
                                                                              expr
                                                                              (let ((a!1 (ite (>= (|List.length_2276| (odds_2281 l_2287)) 0)
                                                                                              (|List.length_2276| (…
                                                                              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 Is_a([], List.tl l) && not Is_a([], l)]
                                                                              proof
                                                                              detailed proof
                                                                              ground_instances4
                                                                              definitions0
                                                                              inductions0
                                                                              search_time
                                                                              0.014s
                                                                              details
                                                                              Expand
                                                                              smt_stats
                                                                              num checks9
                                                                              arith-assume-eqs2
                                                                              arith-make-feasible14
                                                                              arith-max-columns12
                                                                              rlimit count2941
                                                                              arith-cheap-eqs4
                                                                              mk clause15
                                                                              datatype occurs check58
                                                                              mk bool var89
                                                                              arith-lower6
                                                                              datatype splits12
                                                                              decisions22
                                                                              propagations12
                                                                              interface eqs2
                                                                              arith-max-rows4
                                                                              conflicts8
                                                                              datatype accessor ax12
                                                                              arith-bound-propagations-lp1
                                                                              datatype constructor ax16
                                                                              num allocs2582209399
                                                                              final checks14
                                                                              added eqs82
                                                                              del clause13
                                                                              arith eq adapter4
                                                                              arith-upper8
                                                                              memory35.970000
                                                                              max memory53.760000
                                                                              Expand
                                                                              • start[0.014s]
                                                                                  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 Is_a([], List.tl _x_3) && not Is_a([], _x_3))
                                                                                  in
                                                                                  not Is_a([], _x_0) && not Is_a([], 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 Is_a([], List.tl _x_1) && not Is_a([], _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 Is_a([], _x_0) && not Is_a([], l))
                                                                                expansions
                                                                                []
                                                                                rewrite_steps
                                                                                  forward_chaining
                                                                                  • unroll
                                                                                    expr
                                                                                    (|List.length_2276| l_2287)
                                                                                    expansions
                                                                                    • unroll
                                                                                      expr
                                                                                      (|List.length_2276| (odds_2281 (|get.::.1_2269| l_2287)))
                                                                                      expansions
                                                                                      • unroll
                                                                                        expr
                                                                                        (let ((a!1 (>= (|List.length_2276| (odds_2281 (|get.::.1_2269| l_2287))) 0))
                                                                                              (a!3 (|Ordinal.In…
                                                                                        expansions
                                                                                        • unroll
                                                                                          expr
                                                                                          (odds_2281 (|get.::.1_2269| l_2287))
                                                                                          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 `let (_x_0 : int list) = List.tl x in is_sorted ((List.hd _x_0) :: (List.tl _x_0))` from `is_sorted x`
                                                                                          originalis_sorted x
                                                                                          sublet (_x_0 : int list) = List.tl x in is_sorted ((List.hd _x_0) :: (List.tl _x_0))
                                                                                          original ordinalOrdinal.Int (_cnt x)
                                                                                          sub ordinallet (_x_0 : int list) = List.tl x in Ordinal.Int (_cnt ((List.hd _x_0) :: (List.tl _x_0)))
                                                                                          path[List.hd x <= List.hd (List.tl x) && not Is_a([], List.tl x) && not Is_a([], x)]
                                                                                          proof
                                                                                          detailed proof
                                                                                          ground_instances3
                                                                                          definitions0
                                                                                          inductions0
                                                                                          search_time
                                                                                          0.012s
                                                                                          details
                                                                                          Expand
                                                                                          smt_stats
                                                                                          num checks8
                                                                                          arith-assume-eqs2
                                                                                          arith-make-feasible24
                                                                                          arith-max-columns24
                                                                                          arith-conflicts2
                                                                                          rlimit count2742
                                                                                          mk clause39
                                                                                          datatype occurs check13
                                                                                          mk bool var90
                                                                                          arith-lower24
                                                                                          arith-diseq2
                                                                                          datatype splits1
                                                                                          decisions20
                                                                                          arith-propagations1
                                                                                          propagations28
                                                                                          interface eqs2
                                                                                          arith-bound-propagations-cheap1
                                                                                          arith-max-rows9
                                                                                          conflicts8
                                                                                          datatype accessor ax9
                                                                                          minimized lits2
                                                                                          arith-bound-propagations-lp2
                                                                                          datatype constructor ax7
                                                                                          num allocs2774934557
                                                                                          final checks6
                                                                                          added eqs61
                                                                                          del clause27
                                                                                          arith eq adapter20
                                                                                          arith-upper22
                                                                                          memory36.270000
                                                                                          max memory53.760000
                                                                                          Expand
                                                                                          • start[0.012s]
                                                                                              let (_x_0 : int list) = List.tl x in
                                                                                              let (_x_1 : int) = List.hd _x_0 in
                                                                                              let (_x_2 : int) = count.list mk_nat x in
                                                                                              let (_x_3 : int) = count.list mk_nat (_x_1 :: …) in
                                                                                              List.hd x <= _x_1
                                                                                              && not Is_a([], _x_0) && not Is_a([], x) && _x_2 >= 0 && _x_3 >= 0
                                                                                              ==> not (_x_1 <= List.hd … && not Is_a([], …))
                                                                                                  || Ordinal.( << ) (Ordinal.Int _x_3) (Ordinal.Int _x_2)
                                                                                          • simplify
                                                                                            into
                                                                                            let (_x_0 : int list) = List.tl x in
                                                                                            let (_x_1 : int) = List.hd _x_0 in
                                                                                            let (_x_2 : int list) = List.tl _x_0 in
                                                                                            let (_x_3 : int) = count.list mk_nat (_x_1 :: _x_2) in
                                                                                            let (_x_4 : int) = count.list mk_nat x in
                                                                                            (not (_x_1 <= List.hd _x_2 && not Is_a([], _x_2))
                                                                                             || Ordinal.( << ) (Ordinal.Int _x_3) (Ordinal.Int _x_4))
                                                                                            || not
                                                                                               ((((List.hd x <= _x_1 && not Is_a([], _x_0)) && not Is_a([], x))
                                                                                                 && _x_4 >= 0)
                                                                                                && _x_3 >= 0)
                                                                                            expansions
                                                                                            []
                                                                                            rewrite_steps
                                                                                              forward_chaining
                                                                                              • unroll
                                                                                                expr
                                                                                                (|`count.list mk_nat[0]`_2379| x_2368)
                                                                                                expansions
                                                                                                • unroll
                                                                                                  expr
                                                                                                  (|`count.list mk_nat[0]`_2379|
                                                                                                    (|::_3| (|get.::.0_2366| (|get.::.1_2367| x_2368))
                                                                                                            (|get.…
                                                                                                  expansions
                                                                                                  • unroll
                                                                                                    expr
                                                                                                    (let ((a!1 (|`count.list mk_nat[0]`_2379|
                                                                                                                 (|::_3| (|get.::.0_2366| (|get.::.1_2367| x_2…
                                                                                                    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.022s):
                                                                                                     let (x : int list) = [133758; 133758; 133758; 133758; 133758]
                                                                                                    
                                                                                                    Instance
                                                                                                    proof attempt
                                                                                                    ground_instances11
                                                                                                    definitions0
                                                                                                    inductions0
                                                                                                    search_time
                                                                                                    0.022s
                                                                                                    details
                                                                                                    Expand
                                                                                                    smt_stats
                                                                                                    num checks23
                                                                                                    arith-assume-eqs19
                                                                                                    arith-make-feasible83
                                                                                                    arith-max-columns37
                                                                                                    arith-conflicts8
                                                                                                    rlimit count6429
                                                                                                    arith-cheap-eqs27
                                                                                                    mk clause144
                                                                                                    datatype occurs check42
                                                                                                    mk bool var322
                                                                                                    arith-lower46
                                                                                                    arith-diseq16
                                                                                                    datatype splits12
                                                                                                    decisions69
                                                                                                    arith-propagations3
                                                                                                    propagations196
                                                                                                    interface eqs19
                                                                                                    arith-bound-propagations-cheap3
                                                                                                    arith-max-rows20
                                                                                                    conflicts21
                                                                                                    datatype accessor ax39
                                                                                                    arith-bound-propagations-lp3
                                                                                                    datatype constructor ax51
                                                                                                    num allocs2877487270
                                                                                                    final checks41
                                                                                                    added eqs279
                                                                                                    del clause109
                                                                                                    arith eq adapter62
                                                                                                    arith-upper73
                                                                                                    memory36.720000
                                                                                                    max memory53.760000
                                                                                                    Expand
                                                                                                    • start[0.022s] List.length ( :var_0: ) >= 5 && is_sorted ( :var_0: )
                                                                                                    • unroll
                                                                                                      expr
                                                                                                      (is_sorted_64 x_75)
                                                                                                      expansions
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (|List.length_2426| x_75)
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|List.length_2426| (|get.::.1_2425| x_75))
                                                                                                          expansions
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (|List.length_2426| (|get.::.1_2425| (|get.::.1_2425| x_75)))
                                                                                                            expansions
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (is_sorted_64 (|::_3| (|get.::.0_2424| (|get.::.1_2425| x_75))
                                                                                                                                    (|get.::.1_2425…
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (|List.length_2426| (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| x_75))))
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (let ((a!1 (|::_3| (|get.::.0_2424| (|get.::.1_2425| (|get.::.1_2425| x_75)))
                                                                                                                                     (|g…
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (let ((a!1 (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| x_75))))))
                                                                                                                      (|List.l…
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (let ((a!1 (|get.::.0_2424| (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| x_75)))))
                                                                                                                            (a!2 …
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (let ((a!1 (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| x_75))))))
                                                                                                                          (|List.l…
                                                                                                                        expansions
                                                                                                                        • unroll
                                                                                                                          expr
                                                                                                                          (let ((a!1 (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| (|get.::.1_2425| x_75))))))
                                                                                                                            (is_sort…
                                                                                                                          expansions
                                                                                                                          • Sat (Some let (x : int list) = [133758; 133758; 133758; 133758; 133758] )
                                                                                                                          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 47 steps, 0.115s):
                                                                                                                           let (x : int list) = [427723; 427723; 427723; 427723; 427723]
                                                                                                                          
                                                                                                                          Instance
                                                                                                                          proof attempt
                                                                                                                          ground_instances47
                                                                                                                          definitions0
                                                                                                                          inductions0
                                                                                                                          search_time
                                                                                                                          0.115s
                                                                                                                          details
                                                                                                                          Expand
                                                                                                                          smt_stats
                                                                                                                          num checks95
                                                                                                                          arith-assume-eqs138
                                                                                                                          arith-make-feasible1014
                                                                                                                          arith-max-columns80
                                                                                                                          arith-conflicts45
                                                                                                                          rlimit count97873
                                                                                                                          arith-cheap-eqs734
                                                                                                                          mk clause1585
                                                                                                                          datatype occurs check2518
                                                                                                                          mk bool var4940
                                                                                                                          arith-lower1070
                                                                                                                          arith-diseq321
                                                                                                                          datatype splits472
                                                                                                                          decisions3307
                                                                                                                          arith-propagations268
                                                                                                                          propagations7177
                                                                                                                          interface eqs138
                                                                                                                          arith-bound-propagations-cheap268
                                                                                                                          arith-max-rows55
                                                                                                                          conflicts244
                                                                                                                          datatype accessor ax452
                                                                                                                          minimized lits72
                                                                                                                          arith-bound-propagations-lp145
                                                                                                                          datatype constructor ax1403
                                                                                                                          num allocs2962524684
                                                                                                                          final checks288
                                                                                                                          added eqs14425
                                                                                                                          del clause935
                                                                                                                          arith eq adapter600
                                                                                                                          arith-upper925
                                                                                                                          time0.002000
                                                                                                                          memory41.250000
                                                                                                                          max memory53.760000
                                                                                                                          Expand
                                                                                                                          • start[0.115s]
                                                                                                                              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_2469| x_77)
                                                                                                                                expansions
                                                                                                                                • unroll
                                                                                                                                  expr
                                                                                                                                  (is_sorted_64 (|List.rev_2469| x_77))
                                                                                                                                  expansions
                                                                                                                                  • unroll
                                                                                                                                    expr
                                                                                                                                    (is_sorted_64 x_77)
                                                                                                                                    expansions
                                                                                                                                    • unroll
                                                                                                                                      expr
                                                                                                                                      (|List.length_2465| x_77)
                                                                                                                                      expansions
                                                                                                                                      • unroll
                                                                                                                                        expr
                                                                                                                                        (|List.rev_2469| (|get.::.1_2464| x_77))
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (|List.append_2473|
                                                                                                                                            (|List.rev_2469| (|get.::.1_2464| x_77))
                                                                                                                                            (|::_3| (|get.::.0_2463| x_77) |[]_…
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (|List.length_2465| (|get.::.1_2464| x_77))
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77)))
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (|List.append_2473|
                                                                                                                                                  (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77)))
                                                                                                                                                  (|::_3| (|get.::.…
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (let ((a!1 (|::_3| (|get.::.0_2463| (|get.::.1_2464| (|List.rev_2469| x_77)))
                                                                                                                                                                     (|g…
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (|List.length_2465| (|get.::.1_2464| (|get.::.1_2464| x_77)))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (is_sorted_64 (|::_3| (|get.::.0_2463| (|get.::.1_2464| x_77))
                                                                                                                                                                            (|get.::.1_2464…
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (|List.append_2473|
                                                                                                                                                          (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| x_77)))
                                                                                                                                                          (|::_3| (|get.::.…
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (let ((a!1 (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                  (a!2 …
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (|List.length_2465| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (let ((a!1 (|::_3| (|get.::.0_2463| (|get.::.1_2464| (|get.::.1_2464| x_77)))
                                                                                                                                                                                   (|g…
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (let ((a!1 (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                    (|List.a…
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                      (|List.r…
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (let ((a!1 (|get.::.0_2463| (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| x_77)))))
                                                                                                                                                                            (a!2 …
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                              (a!2 …
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                            (|List.l…
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (let ((a!1 (|get.::.0_2463| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                  (a!2 …
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (let ((a!1 (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                    (a!2 …
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                  (|List.a…
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                    (|List.r…
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                      (|List.a…
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                        (|List.l…
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                          (is_sort…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                            (|List.a…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                                  (a!2 …
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                                    (a!2 …
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                  (|List.r…
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| x_77))))))
                                                                                                                                                                                                      (is_sort…
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                          (|List.l…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                            (is_sort…
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                              (|List.a…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                                (|List.a…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77)))))
                                                                                                                                                                                                                        (a!2 …
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                                      (|List.r…
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                                        (let ((a!2…
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| (|get.::.1_2464| x_77))))))
                                                                                                                                                                                                                            (|List.a…
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_2464| (|get.::.1_2464| (|get.::.1_2464| (|List.rev_2469| x_77))))))
                                                                                                                                                                                                                              (is_sort…
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • Sat (Some let (x : int list) = [427723; 427723; 427723; 427723; 427723] )

                                                                                                                                                                                                                            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 (odds (List.tl (odds (List.tl (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 merge (if _x_2 then _x_0 else (List.tl _x_0)) (if _x_2 then List.tl _x_1 else _x_1)
                                                                                                                                                                                                                            • 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)
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • odds (odds x)
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (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 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 (odds (odds x)))
                                                                                                                                                                                                                            • let (_x_0 : int list) = odds (odds (odds x)) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                            • odds (odds (odds (odds (List.tl x))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • odds (List.tl x)
                                                                                                                                                                                                                            • 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 (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds x))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                            • odds x
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (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)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (odds x))))
                                                                                                                                                                                                                            • odds (odds (List.tl x))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (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 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 x)))
                                                                                                                                                                                                                            • 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)
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl x))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                            • is_sorted (merge_sort 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)
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (List.tl (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds x))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (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 merge (if _x_6 then _x_4 else (List.tl _x_4)) (if _x_6 then List.tl _x_5 else _x_5)
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds x)))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds x))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl x)))
                                                                                                                                                                                                                            • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                            • merge_sort (odds 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 (odds (List.tl (odds x)))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds x))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (List.tl 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)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl 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 (odds (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            • let (_x_0 : int list) = odds (odds x) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (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)
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • merge_sort x
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                            • let (_x_0 : int list) = List.tl (List.tl (merge_sort x)) in is_sorted ((List.hd _x_0) :: (List.tl _x_0))
                                                                                                                                                                                                                            • let (_x_0 : int list) = odds (List.tl (odds x)) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                            • let (_x_0 : int list) = List.tl (merge_sort x) in is_sorted ((List.hd _x_0) :: (List.tl _x_0))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                            • let (_x_0 : int list) = List.tl (List.tl (List.tl (merge_sort x))) in is_sorted ((List.hd _x_0) :: (List.tl _x_0))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds x))))
                                                                                                                                                                                                                            • odds (odds (odds (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)))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                            blocked
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (odds x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds (List.tl (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)
                                                                                                                                                                                                                            • odds (odds (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 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 (odds (odds (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 (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds (List.tl 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)
                                                                                                                                                                                                                            • odds (odds (odds (odds (odds (List.tl x)))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (odds (odds x)))))
                                                                                                                                                                                                                            • 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 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 (List.tl (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 (List.tl (odds (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (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)
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds (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)))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (odds (odds x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (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 (odds (List.tl (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (odds (odds x)))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))))))
                                                                                                                                                                                                                            • 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 (List.tl (odds (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)))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds (odds x)))))
                                                                                                                                                                                                                            • let (_x_0 : int list) = List.tl (List.tl (List.tl (List.tl (merge_sort x)))) in is_sorted ((List.hd _x_0) :: (List.tl _x_0))
                                                                                                                                                                                                                            • 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)
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            • odds (odds (odds (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)
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl 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 (List.tl (odds (odds 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 (List.tl (odds x)))))))
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (odds (List.tl (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (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 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)
                                                                                                                                                                                                                            • 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 (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (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 (odds (odds (odds (odds (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (odds (odds (odds x)))))
                                                                                                                                                                                                                            • let (_x_0 : int list) = odds (odds (List.tl (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 (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (odds (odds x))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (odds (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 (odds (odds (List.tl (odds 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)))
                                                                                                                                                                                                                            • odds (odds (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                            • let (_x_0 : int list) = odds (odds (odds (List.tl (odds x)))) in merge (merge_sort (odds _x_0)) (merge_sort (odds (List.tl _x_0)))
                                                                                                                                                                                                                            • odds (odds (odds (List.tl (odds (List.tl (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) = List.tl _x_3 in let (_x_5 : int list) = if _x_2 then List.tl _x_1 else _x_1 in let (_x_6 : bool) = List.hd _x_5 <= List.hd _x_3 in let (_x_7 : int list) = List.tl (if _x_6 then … else _x_4) in let (_x_8 : int list) = List.tl _x_5 in let (_x_9 : int list) = if _x_6 then _x_8 else _x_5 in let (_x_10 : int list) = if _x_6 then _x_3 else _x_4 in let (_x_11 : bool) = List.hd _x_9 <= List.hd _x_10 in let (_x_12 : bool) = List.hd (if _x_11 then List.tl _x_9 else _x_9) <= List.hd (if _x_11 then _x_10 else (List.tl _x_10)) in let (_x_13 : int list) = List.tl (if _x_6 then _x_8 else …) in merge (if _x_12 then if _x_11 then if _x_6 then … else _x_4 else _x_7 else (List.tl (if _x_11 then if _x_6 then … else _x_4 else _x_7))) (if _x_12 then List.tl (if _x_11 then _x_13 else if _x_6 then _x_8 else …) else if _x_11 then _x_13 else if _x_6 then _x_8 else …)
                                                                                                                                                                                                                            • 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)
                                                                                                                                                                                                                            • 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)))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (odds (odds x))))))
                                                                                                                                                                                                                            • odds (List.tl (odds (List.tl (odds (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                            • 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 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 (odds (odds (List.tl (odds (List.tl (odds 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)))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (odds (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                            • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                            • merge_sort (odds (List.tl (odds (List.tl (odds (odds (odds x)))))))
                                                                                                                                                                                                                            • merge_sort (odds (odds (List.tl (odds (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                            proof attempt
                                                                                                                                                                                                                            ground_instances100
                                                                                                                                                                                                                            definitions0
                                                                                                                                                                                                                            inductions0
                                                                                                                                                                                                                            search_time
                                                                                                                                                                                                                            1.917s
                                                                                                                                                                                                                            Expand
                                                                                                                                                                                                                            • start[1.917s] is_sorted (merge_sort ( :var_0: ))
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (merge_sort_56 x_79)
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (is_sorted_64 (merge_sort_56 x_79))
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (odds_1824 (|get.::.1_1823| x_79))
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (merge_sort_56 (odds_1824 (|get.::.1_1823| x_79)))
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (odds_1824 x_79)
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (odds_1824 (|get.::.1_1823| (|get.::.1_1823| x_79)))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (merge_sort_56 (odds_1824 x_79))
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (merge_14 (merge_sort_56 (odds_1824 x_79))
                                                                                                                                                                                                                                                      (merge_sort_56 (odds_1824 (|get.::.1_1823| x_79…
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (odds_1824 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (let ((a!1 (|::_3| (|get.::.0_1822| (|get.::.1_1823| (merge_sort_56 x_79)))
                                                                                                                                                                                                                                                                   (|get…
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                    (odds_18…
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                        (merge_sort_56 a!1))
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (odds_1824 (odds_1824 (|get.::.1_1823| x_79)))
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (merge_sort_56 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_1822| (merge_sort_56 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                  (a!4 (|get.::…
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (let ((a!1 (merge_sort_56 (odds_1824 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                    (a!2 (odds_1824 (|g…
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (odds_1824 (|get.::.1_1823| (odds_1824 x_79)))
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (merge_sort_56 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (odds_1824 (odds_1824 x_79))
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (merge_sort_56 (odds_1824 (odds_1824 x_79)))
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (let ((a!1 (merge_sort_56 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                          (merge_14 (merge_sort_…
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                            (odds_1824 a!1…
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (odds_1824 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 x_79))))
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                (odds_18…
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                  (odds_1824 (|g…
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                    (odds_1824 a!1))
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                      (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.0_1822| (|get.::.1_1823| (|get.::.1_1823| (merge_sort_56 x_79)))))
                                                                                                                                                                                                                                                                                              (a!2 (|…
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                              (merge_sort_56 a!1))
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                    (a!2 (|get.::.1_1823| (…
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.0_1822| (merge_sort_56 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                      (a!3 (|get.::…
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                    (odds_18…
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                      (odds_1824 a!1…
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                        (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                          (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                              (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                (merge_sort_56 a!1))
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.1_1823| (…
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                      (merge_sort_56 a!1))
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                        (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (odds_1824 (odds_1824 (odds_1824 x_79)))
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (merge_sort_56 (odds_1824 (odds_1824 (odds_1824 x_79))))
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (merge_sort_56 (odds_1824 (odds_1824 (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                  (a!2 (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (merge_sort_56 (odds_1824 (|get.::.1_1823| (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                    (a!2 (|get.::.0_182…
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                  (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                    (odds_1824 (|g…
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                      (odds_18…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                        (odds_1824 (|g…
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                          (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                            (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                              (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                  (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                    (odds_1824 (odds_182…
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                      (merge_14 (merge_sor…
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (merge_sort_56 x_79))))))
                                                                                                                                                                                                                                                                                                                                                        (is_sorted…
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                          (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                          (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                              (odds_1824 (|get.::.1_1823…
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                (odds_1824 (|g…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                    (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                        (merge_14 (merge_sort_56 (…
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                                                                                              (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                (a!2 (odds_1824 (…
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.0_1822| (merge_sort_56 (odds_1824 (|get.::.1_1823| x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                  (a!3 (|get.::…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                (odds_1824 (|g…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                  (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| (|get.::.1_1823| x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!2…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                      (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1823| (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                        (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                          (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                            (odds_1824 (|get.::.1_1823…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                              (odds_1824 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                    (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (merge_14 (merge_sort_56 (…
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1823| (odds_1824 (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (odds_1824 (odds_1824 (odds_1824 (odds_1824 x_79))))
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_56 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                  (odds_1824 (odds_182…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1824 (odds_1824 (odds_1824 (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (a!2 (|get.::.1_1823| (odds_1…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1824 (|get.::.1_1823| (odds_1824 (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (a!2 (merge_sort_56 (od…
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (odds_1824 (|get.::.1_1823…
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_56 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (odds_1824 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                    (a!2 (odds_1824 (…
                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (merge_sort_56 (odds_1824 (|get.::.1_1823| (odds_1824 x_79)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.0_182…
                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1824 (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                    (merge_sort_56 (odds_1824 …
                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1823| (odds_1824 (|get.::.1_1823| (odds_1824 x_79))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                                                    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 Is_a([], List.tl x) && not Is_a([], x)) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         && not Is_a([], List.tl x) && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. not Is_a([], List.tl x) && not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not Is_a([], 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. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. 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. is_sorted (merge_sort (odds x2))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], x2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 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. is_sorted (merge_sort gen_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], x2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 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. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], x2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 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. is_sorted gen_4
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], x2)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. 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 Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (not (List.hd x < List.hd y) && not Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                         && not Is_a([], y) && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                            && not Is_a([], 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 Is_a([], y)) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not ((List.hd y <= List.hd x && not Is_a([], y)) && not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not Is_a([], 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 definition of merge to the following 2 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                     C3. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C4. is_sorted ((List.hd y) :: (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 2.2 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. is_sorted ((List.hd y) :: (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 2.1 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not Is_a([], 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 definition of merge to the following 2 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C3. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C4. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     C5. is_sorted ((List.hd x) :: (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 1.2 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                     C3. is_sorted ((List.hd x) :: (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    But we verify Subgoal 1.1 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                     Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                        (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances19
                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions12
                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                    1.863s
                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks10
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-assume-eqs3
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-make-feasible22
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-columns16
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count233714
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-cheap-eqs2
                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause165
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check61
                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var259
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-lower9
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-diseq2
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits17
                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions54
                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations127
                                                                                                                                                                                                                                                                                                                                                                                                                                    interface eqs3
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-rows7
                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts17
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax13
                                                                                                                                                                                                                                                                                                                                                                                                                                    minimized lits2
                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax29
                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks14
                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs300
                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause116
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter11
                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-upper13
                                                                                                                                                                                                                                                                                                                                                                                                                                    memory118.430000
                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory118.430000
                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs32679905653.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.863s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                        is_sorted ( :var_0: ) && is_sorted ( :var_1: )
                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> is_sorted (merge ( :var_0: ) ( :var_1: ))
                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                      (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[1.863s, "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 Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                    (not (List.hd x < List.hd y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (List.hd x < List.hd y) && φ x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> φ x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not Is_a([], 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 Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                               let (_x_6 : bool) = not Is_a([], 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 Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                       let (_x_2 : bool) = not Is_a([], 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)) || Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || Is_a([], 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) || Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          || Is_a([], 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) || Is_a([], x)) || Is_a([], 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[1.861s, "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) || Is_a([], x)) || Is_a([], 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) = Is_a([], y) || Is_a([], 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 : int) = List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_5 : bool) = List.hd y <= _x_4 in
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_6 : bool) = not (is_sorted x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_7 : bool) = not (is_sorted y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_8 : bool) = is_sorted (_x_4 :: _x_2) in
                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((((_x_0 || _x_3) || is_sorted _x_1) || _x_5) || _x_6) || _x_7) || _x_8)
                                                                                                                                                                                                                                                                                                                                                                                                                                            && (((((_x_0 || _x_5) || _x_6) || _x_7) || _x_8) || not _x_3)
                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                            [merge, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                • 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)) || Is_a([], x)) || Is_a([], 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[1.861s, "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)) || Is_a([], x)) || Is_a([], 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) = Is_a([], y) || Is_a([], x) 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 : int) = List.hd y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_5 : bool) = not (_x_4 <= List.hd x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_6 : bool) = not (is_sorted x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_7 : bool) = not (is_sorted y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_8 : bool) = is_sorted (_x_4 :: _x_2) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                ((((((_x_0 || _x_3) || is_sorted _x_1) || _x_5) || _x_6) || _x_7) || _x_8)
                                                                                                                                                                                                                                                                                                                                                                                                                                                && (((((_x_0 || _x_5) || _x_6) || _x_7) || not _x_3) || _x_8)
                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                [merge, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                  let (_x_0 : bool) = List.hd y <= List.hd x in let (_x_1 : bool) = not Is_a([], y) in let (_x_2 : bool) = not Is_a([], 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[1.861s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_1 : bool) = not Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_2 : bool) = not Is_a([], 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 Is_a([], List.tl x) && not Is_a([], x)) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not Is_a([], List.tl x) && φ (odds (List.tl x)) && φ (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                
                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. not Is_a([], List.tl x) && not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. not Is_a([], 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. is_sorted (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 H1. is_sorted (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                 C0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 C2. 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                definitions5
                                                                                                                                                                                                                                                                                                                                                                                                                                                inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                0.256s
                                                                                                                                                                                                                                                                                                                                                                                                                                                Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[0.256s, "Goal"] is_sorted (merge_sort ( :var_0: ))
                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                  is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.256s, "1"] is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                  • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    :scheme (not (not Is_a([], List.tl x) && not Is_a([], x)) ==> φ x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not Is_a([], 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 Is_a([], _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                           let (_x_2 : bool) = not Is_a([], 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 Is_a([], List.tl x) && not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge_sort x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (((Is_a([], x) || Is_a([], _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 (((Is_a([], x) || Is_a([], _x_0)) || not (is_sorted (merge_sort (odds _x_0)))) || not (is_sorted (merge_sort (odds x)))) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.256s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                          let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((Is_a([], x) || Is_a([], _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
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((Is_a([], _x_0) || Is_a([], 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 Is_a([], List.tl x) && not Is_a([], x) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[0.256s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                not Is_a([], List.tl x) && not Is_a([], x) || is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                                              true
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                              [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 (_cnt y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                          sub ordinalOrdinal.Int (_cnt (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          path[List.hd y = x && not Is_a([], y)]
                                                                                                                                                                                                                                                                                                                                                                                                                                                          proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                          detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                          ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                          definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                          inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                          search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                          0.011s
                                                                                                                                                                                                                                                                                                                                                                                                                                                          details
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith-make-feasible7
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith-max-columns12
                                                                                                                                                                                                                                                                                                                                                                                                                                                          rlimit count3672
                                                                                                                                                                                                                                                                                                                                                                                                                                                          mk clause19
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype occurs check21
                                                                                                                                                                                                                                                                                                                                                                                                                                                          mk bool var52
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith-lower3
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype splits3
                                                                                                                                                                                                                                                                                                                                                                                                                                                          decisions9
                                                                                                                                                                                                                                                                                                                                                                                                                                                          propagations14
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith-max-rows4
                                                                                                                                                                                                                                                                                                                                                                                                                                                          conflicts3
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                          datatype constructor ax7
                                                                                                                                                                                                                                                                                                                                                                                                                                                          final checks6
                                                                                                                                                                                                                                                                                                                                                                                                                                                          added eqs38
                                                                                                                                                                                                                                                                                                                                                                                                                                                          del clause6
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                          arith-upper6
                                                                                                                                                                                                                                                                                                                                                                                                                                                          memory103.390000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          max memory118.430000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          num allocs37491948318.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[0.011s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_0 : int) = count.list (const 0) y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_1 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_2 : int) = count.list (const 0) _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_3 : bool) = List.hd _x_1 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                              let (_x_4 : bool) = not Is_a([], _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                              List.hd y = x && not Is_a([], 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 : bool) = List.hd _x_0 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_2 : bool) = not Is_a([], _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_3 : int) = count.list (const 0) _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_4 : int) = count.list (const 0) y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (not (_x_1 && _x_2) && not (not _x_1 && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                             || Ordinal.( << ) (Ordinal.Int _x_3) (Ordinal.Int _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (((List.hd y = x && not Is_a([], y)) && _x_4 >= 0) && _x_3 >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            []
                                                                                                                                                                                                                                                                                                                                                                                                                                                            rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                (|`count.list (const 0)[0]`_4885| y_4871)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (|`count.list (const 0)[0]`_4885| (|get.::.1_4864| y_4871))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|Ordinal.<<_126| (|Ordinal.Int_111|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (|`count.list (const 0)[0]`_4885| (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    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 (_cnt y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    sub ordinalOrdinal.Int (_cnt (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    path[not (List.hd y = x) && not Is_a([], y)]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0.013s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-make-feasible7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-columns12
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count1847
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause19
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check21
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var52
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-lower3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions9
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations14
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-max-rows4
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax7
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks6
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs37
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause6
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith-upper6
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    memory100.770000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory118.430000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs37321146955.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.013s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int) = count.list (const 0) y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : ty_0 list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_2 : int) = count.list (const 0) _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_3 : bool) = List.hd _x_1 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_4 : bool) = not Is_a([], _x_1) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        not (List.hd y = x) && not Is_a([], 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 : bool) = List.hd _x_0 = x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_2 : bool) = not Is_a([], _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_3 : int) = count.list (const 0) _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      let (_x_4 : int) = count.list (const 0) y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (not (_x_1 && _x_2) && not (not _x_1 && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || Ordinal.( << ) (Ordinal.Int _x_3) (Ordinal.Int _x_4))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || not (((not (List.hd y = x) && not Is_a([], y)) && _x_4 >= 0) && _x_3 >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|`count.list (const 0)[0]`_4885| y_4871)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|`count.list (const 0)[0]`_4885| (|get.::.1_4864| y_4871))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (|Ordinal.<<_126| (|Ordinal.Int_111|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (|`count.list (const 0)[0]`_4885| (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              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 Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (not (List.hd x < List.hd y) && not Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && not Is_a([], y) && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not Is_a([], 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 Is_a([], y)) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not ((List.hd y <= List.hd x && not Is_a([], y)) && not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not Is_a([], 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.194s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.194s, "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.194s, "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 Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (not (List.hd x < List.hd y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               && not Is_a([], y) && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not Is_a([], y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (List.hd x < List.hd y) && φ a x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ a x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not Is_a([], 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 Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         let (_x_3 : bool) = not Is_a([], 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 Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_2 : bool) = not Is_a([], 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((Is_a([], x) || Is_a([], 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((Is_a([], x) || Is_a([], 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 (((Is_a([], x) || Is_a([], 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.193s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : int) = num_occurs a y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((Is_a([], x) || Is_a([], 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 (((Is_a([], x) || Is_a([], 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.193s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_0 : int list) = List.tl y in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_1 : int) = num_occurs a x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((Is_a([], x) || Is_a([], 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 Is_a([], y) in let (_x_2 : bool) = not Is_a([], 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.193s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : bool) = List.hd y <= List.hd x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_1 : bool) = not Is_a([], y) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_2 : bool) = not Is_a([], 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 (List.hd x = a && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (not (List.hd x = a) && not Is_a([], x)) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && (not Is_a([], x) && not (List.hd x = a) && φ a (List.tl x) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              && (not Is_a([], 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 (List.hd x = a && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H3. not (not (List.hd x = a) && not Is_a([], 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H3. not (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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. 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. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C3. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H3. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C3. 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. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C3. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. List.hd x = List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. 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 Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H3. 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 1.4:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. 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. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H3. 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))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. 0 =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. 0 = num_occurs (List.hd x) (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C2. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H0. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C1. 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. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           H2. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           C0. Is_a([], 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.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:def odds)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (:induct num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          definitions48
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1.262s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • start[1.262s, "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.261s, "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 (List.hd x = a && not Is_a([], x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && not (not (List.hd x = a) && not Is_a([], x)) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (not Is_a([], x) && not (List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not Is_a([], x) && List.hd x = a && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Split (let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_1 : bool) = not (_x_0 = []) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_2 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_3 : bool)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         = not (not (x = []) && _x_1)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || _x_2 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_4 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_5 : bool) = not Is_a([], x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_6 : bool) = not _x_4 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_7 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     let (_x_8 : bool)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         = not (_x_1 && not (_x_7 = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (odds _x_7) = num_occurs a _x_0 + -1 * _x_2
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ((_x_3 || not (not (_x_4 && _x_5) && not (_x_6 && _x_5)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && (_x_3 || not ((_x_5 && _x_6) && _x_8)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (_x_3 || not ((_x_5 && _x_4) && _x_8))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     :cases [let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_1 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_2 : bool) = not Is_a([], x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             (((x = [] || _x_0 = []) || _x_1 && _x_2) || not _x_1 && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || num_occurs a (odds _x_0) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_1 : bool) = _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_3 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ((((x = [] || _x_1) || Is_a([], x)) || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not _x_1 && not (_x_2 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> num_occurs a (odds _x_2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a _x_0 + -1 * _x_3))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || _x_3 = num_occurs a x + -1 * num_occurs a (odds x);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_1 : bool) = _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             let (_x_3 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ((((x = [] || _x_1) || Is_a([], x)) || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (not _x_1 && not (_x_2 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> num_occurs a (odds _x_2) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a _x_0 + -1 * _x_3))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || _x_3 = num_occurs a x + -1 * num_occurs a (odds x)])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : int list) = List.tl x in let (_x_1 : bool) = _x_0 = [] in let (_x_2 : int list) = List.tl _x_0 in let (_x_3 : int) = num_occurs a (odds _x_0) in ((((x = [] || _x_1) || Is_a([], x)) || not (List.hd x = a)) || not (not _x_1 && not (_x_2 = []) ==> num_occurs a (odds _x_2) = num_occurs a _x_0 + -1 * _x_3)) || _x_3 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • start[1.260s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_1 : bool) = _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    let (_x_3 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ((((x = [] || _x_1) || Is_a([], x)) || not (List.hd x = a))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (not _x_1 && not (_x_2 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> num_occurs a (odds _x_2) = num_occurs a _x_0 + -1 * _x_3))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    || _x_3 = 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) = Is_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 : 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 : int list) = List.tl x in let (_x_1 : bool) = _x_0 = [] in let (_x_2 : int list) = List.tl _x_0 in let (_x_3 : int) = num_occurs a (odds _x_0) in ((((x = [] || _x_1) || Is_a([], x)) || List.hd x = a) || not (not _x_1 && not (_x_2 = []) ==> num_occurs a (odds _x_2) = num_occurs a _x_0 + -1 * _x_3)) || _x_3 = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.261s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_1 : bool) = _x_0 = [] in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_2 : int list) = List.tl _x_0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        let (_x_3 : int) = num_occurs a (odds _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((((x = [] || _x_1) || Is_a([], x)) || List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (not _x_1 && not (_x_2 = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> num_occurs a (odds _x_2) = num_occurs a _x_0 + -1 * _x_3))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || _x_3 = 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 || Is_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 || not (_x_5 = 1 + _x_6 + _x_8)) || _x_12) || _x_11))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && ((_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 : int list) = List.tl x in let (_x_1 : bool) = List.hd x = a in let (_x_2 : bool) = not Is_a([], x) in (((x = [] || _x_0 = []) || _x_1 && _x_2) || not _x_1 && _x_2) || num_occurs a (odds _x_0) = num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[1.261s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_0 : int list) = List.tl x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_1 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            let (_x_2 : bool) = not Is_a([], x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((x = [] || _x_0 = []) || _x_1 && _x_2) || not _x_1 && _x_2)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || num_occurs a (odds _x_0) = 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 Is_a([], List.tl x) && not Is_a([], x)) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not Is_a([], List.tl x) && φ a (odds (List.tl x)) && φ a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      2 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. not Is_a([], List.tl x) && not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      This simplifies, using the definitions of merge_sort and num_occurs to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C2. num_occurs a x = 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      This simplifies, using the definition of num_occurs to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2.3':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C2. num_occurs a (List.tl x) = 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. num_occurs a x = 1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      This simplifies, using the definition of num_occurs to:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2.2':
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. num_occurs (List.hd x) (List.tl x) = 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a x = 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H0. not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. not Is_a([], 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. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C3. 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. num_occurs a (odds x) = num_occurs a (merge_sort (odds x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H1. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       H2. num_occurs a (List.tl x) + -1 * num_occurs a (odds x) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           -1 + num_occurs a (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C0. Is_a([], List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C1. Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       C2. 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      definitions17
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1.532s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[1.532s, "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[1.532s, "1"] num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • induction on (functional merge_sort)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          :scheme (not (not Is_a([], List.tl x) && not Is_a([], x)) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not Is_a([], 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 Is_a([], _x_0) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 let (_x_2 : bool) = not Is_a([], 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 Is_a([], List.tl x) && not Is_a([], 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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (((Is_a([], x) || Is_a([], _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 (((Is_a([], x) || Is_a([], _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[1.531s, "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
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((Is_a([], x) || Is_a([], _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)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  = (Is_a([], _x_0) || Is_a([], 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) || not (_x_7 = -1 + _x_9)) || _x_6 = -1 + _x_10)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              [merge_sort, num_occurs, merge_sort, num_occurs, num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              num_occurs_arith
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              not Is_a([], List.tl x) && not Is_a([], x) || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[1.531s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  not Is_a([], List.tl x) && not Is_a([], x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || num_occurs a x = num_occurs a (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_0 : bool) = not Is_a([], List.tl x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_1 : bool) = Is_a([], x) in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_2 : bool) = _x_0 || _x_1 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_3 : bool) = List.hd x = a in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_4 : int) = num_occurs a x in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                let (_x_5 : bool) = _x_4 = 0 in
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                (((_x_2 || _x_3) || _x_5) && ((_x_2 || not _x_3) || _x_4 = 1))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && ((_x_0 || not _x_1) || _x_5)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [num_occurs, merge_sort, num_occurs, num_occurs, num_occurs, num_occurs,
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 merge_sort]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • Subproof

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            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)!