Verifying Merge Sort in Imandra

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

Let's verify it in Imandra!

The main idea

The main idea of merge sort is as follows:

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

Merging two lists

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

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

Termination proof

call `merge (List.tl l) m` from `merge l m`
originalmerge l m
submerge (List.tl l) m
original ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
sub ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count (List.tl l)); Ordinal.Int (Ordinal.count m)]
path[List.hd l < List.hd m && not (m = []) && not (l = [])]
proof
detailed proof
ground_instances8
definitions0
inductions0
search_time
0.031s
details
Expand
smt_stats
arith offset eqs36
num checks18
arith assert lower156
arith pivots85
rlimit count59824
mk clause304
datatype occurs check348
mk bool var700
arith assert upper147
datatype splits59
decisions420
arith add rows324
arith bound prop12
propagations589
interface eqs13
conflicts50
arith fixed eqs104
datatype accessor ax70
minimized lits3
arith conflicts7
arith assert diseq21
datatype constructor ax87
num allocs6982431
final checks41
added eqs923
del clause196
arith eq adapter120
memory6.620000
max memory9.760000
Expand
  • start[0.031s]
      List.hd l < List.hd m
      && not (m = [])
         && not (l = [])
            && Ordinal.count l >= 0
               && Ordinal.count m >= 0
                  && Ordinal.count (List.tl l) >= 0 && Ordinal.count m >= 0
      ==> not
          (List.hd (List.tl l) < List.hd m
           && not (m = []) && not (List.tl l = []))
          && not
             (not (List.hd (List.tl l) < List.hd m)
              && not (m = []) && not (List.tl l = []))
          || Ordinal.( << )
             (if [Ordinal.Int (Ordinal.count (List.tl l));
                  Ordinal.Int (Ordinal.count m)]
                 = []
              then … else …)
             …
  • simplify
    into
    (not
     (((((not (List.hd m <= List.hd l) && not (m = [])) && not (l = []))
        && Ordinal.count l >= 0)
       && Ordinal.count m >= 0)
      && Ordinal.count (List.tl l) >= 0)
     || not
        ((not (List.hd m <= List.hd (List.tl l)) && not (m = []))
         && not (List.tl l = []))
        && not
           ((List.hd m <= List.hd (List.tl l) && not (m = []))
            && not (List.tl l = [])))
    || Ordinal.( << )
       (Ordinal.plus
        (Ordinal.shift (Ordinal.Int (Ordinal.count (List.tl l))) (Ordinal.Int 1))
        (Ordinal.Int (Ordinal.count m)))
       (Ordinal.plus
        (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
        (Ordinal.Int (Ordinal.count m)))
    expansions
    []
    rewrite_steps
      forward_chaining
      • unroll
        expr
        (|Ordinal.shift_127|
          (|Ordinal.Int_93| (|count_`int list`_1096| l_1083))
          (|Ordinal.Int_93| 1))
        expansions
        • unroll
          expr
          (|Ordinal.plus_113|
            (|Ordinal.shift_127|
              (|Ordinal.Int_93| (|count_`int list`_1096| l_1083))
           …
          expansions
          • unroll
            expr
            (|Ordinal.shift_127|
              (|Ordinal.Int_93| (|count_`int list`_1096| (|get.::.1_1082| l_1083)))
              (|Ord…
            expansions
            • unroll
              expr
              (let ((a!1 (|Ordinal.shift_127|
                           (|Ordinal.Int_93| (|count_`int list`_1096|
                          …
              expansions
              • unroll
                expr
                (let ((a!1 (|Ordinal.shift_127|
                             (|Ordinal.Int_93| (|count_`int list`_1096|
                            …
                expansions
                • unroll
                  expr
                  (|count_`int list`_1096| (|get.::.1_1082| l_1083))
                  expansions
                  • unroll
                    expr
                    (|count_`int list`_1096| m_1084)
                    expansions
                    • unroll
                      expr
                      (|count_`int list`_1096| l_1083)
                      expansions
                      • unsat
                        (let ((a!1 (|get.Ordinal.Cons.1_1088|
                                     (|Ordinal.shift_127|
                                       (|Ordinal.Int…

                      call `merge l (List.tl m)` from `merge l m`
                      originalmerge l m
                      submerge l (List.tl m)
                      original ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count m)]
                      sub ordinalOrdinal.of_list [Ordinal.Int (Ordinal.count l); Ordinal.Int (Ordinal.count (List.tl m))]
                      path[not (List.hd l < List.hd m) && not (m = []) && not (l = [])]
                      proof
                      detailed proof
                      ground_instances13
                      definitions0
                      inductions0
                      search_time
                      0.046s
                      details
                      Expand
                      smt_stats
                      arith offset eqs19
                      num checks28
                      arith assert lower398
                      arith pivots174
                      rlimit count39156
                      mk clause583
                      datatype occurs check681
                      mk bool var1570
                      arith assert upper391
                      datatype splits137
                      decisions987
                      arith add rows543
                      arith bound prop21
                      propagations1504
                      interface eqs11
                      conflicts73
                      arith fixed eqs223
                      datatype accessor ax196
                      minimized lits5
                      arith conflicts11
                      arith assert diseq58
                      datatype constructor ax240
                      num allocs1401350
                      final checks57
                      added eqs1998
                      del clause341
                      arith eq adapter302
                      memory6.680000
                      max memory6.680000
                      Expand
                      • start[0.046s]
                          not (List.hd l < List.hd m)
                          && not (m = [])
                             && not (l = [])
                                && Ordinal.count l >= 0
                                   && Ordinal.count m >= 0
                                      && Ordinal.count l >= 0 && Ordinal.count (List.tl m) >= 0
                          ==> not
                              (List.hd l < List.hd (List.tl m)
                               && not (List.tl m = []) && not (l = []))
                              && not
                                 (not (List.hd l < List.hd (List.tl m))
                                  && not (List.tl m = []) && not (l = []))
                              || Ordinal.( << )
                                 (if [Ordinal.Int (Ordinal.count l);
                                      Ordinal.Int (Ordinal.count (List.tl m))]
                                     = []
                                  then … else …)
                                 …
                      • simplify
                        into
                        (not
                         (((((List.hd m <= List.hd l && not (m = [])) && not (l = []))
                            && Ordinal.count l >= 0)
                           && Ordinal.count m >= 0)
                          && Ordinal.count (List.tl m) >= 0)
                         || not
                            ((not (List.hd (List.tl m) <= List.hd l) && not (List.tl m = []))
                             && not (l = []))
                            && not
                               ((List.hd (List.tl m) <= List.hd l && not (List.tl m = []))
                                && not (l = [])))
                        || Ordinal.( << )
                           (Ordinal.plus
                            (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
                            (Ordinal.Int (Ordinal.count (List.tl m))))
                           (Ordinal.plus
                            (Ordinal.shift (Ordinal.Int (Ordinal.count l)) (Ordinal.Int 1))
                            (Ordinal.Int (Ordinal.count m)))
                        expansions
                        []
                        rewrite_steps
                          forward_chaining
                          • unroll
                            expr
                            (|Ordinal.plus_113|
                              (|Ordinal.shift_127|
                                (|Ordinal.Int_93| (|count_`int list`_1096| l_1083))
                             …
                            expansions
                            • unroll
                              expr
                              (|Ordinal.shift_127|
                                (|Ordinal.Int_93| (|count_`int list`_1096| l_1083))
                                (|Ordinal.Int_93| 1))
                              expansions
                              • unroll
                                expr
                                (|Ordinal.plus_113|
                                  (|Ordinal.shift_127|
                                    (|Ordinal.Int_93| (|count_`int list`_1096| l_1083))
                                 …
                                expansions
                                • unroll
                                  expr
                                  (let ((a!1 (|Ordinal.plus_113|
                                               (|Ordinal.shift_127|
                                                 (|Ordinal.Int_93| (|…
                                  expansions
                                  • unroll
                                    expr
                                    (|count_`int list`_1096| (|get.::.1_1082| m_1084))
                                    expansions
                                    • unroll
                                      expr
                                      (|count_`int list`_1096| m_1084)
                                      expansions
                                      • unroll
                                        expr
                                        (|count_`int list`_1096| l_1083)
                                        expansions
                                        • unroll
                                          expr
                                          (|count_`int list`_1096| (|get.::.1_1082| l_1083))
                                          expansions
                                          • unroll
                                            expr
                                            (|count_`int list`_1096| (|get.::.1_1082| (|get.::.1_1082| m_1084)))
                                            expansions
                                            • unroll
                                              expr
                                              (let ((a!1 (|get.Ordinal.Cons.2_1089|
                                                           (|Ordinal.shift_127|
                                                             (|Ordinal.Int…
                                              expansions
                                              • unroll
                                                expr
                                                (let ((a!1 (|get.Ordinal.Cons.2_1089|
                                                             (|Ordinal.shift_127|
                                                               (|Ordinal.Int…
                                                expansions
                                                • unroll
                                                  expr
                                                  (let ((a!1 (|Ordinal.plus_113|
                                                               (|Ordinal.shift_127|
                                                                 (|Ordinal.Int_93| (|…
                                                  expansions
                                                  • unroll
                                                    expr
                                                    (let ((a!1 (|Ordinal.plus_113|
                                                                 (|Ordinal.shift_127|
                                                                   (|Ordinal.Int_93| (|…
                                                    expansions
                                                    • unsat
                                                      (let ((a!1 (|Ordinal.plus_113|
                                                                   (|Ordinal.shift_127|
                                                                     (|Ordinal.Int_93| (|…

                                                    Let's experiment a bit with merge.

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

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

                                                    Dividing into sublists

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

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

                                                    Termination proof

                                                    call `odds (List.tl (List.tl l))` from `odds l`
                                                    originalodds l
                                                    subodds (List.tl (List.tl l))
                                                    original ordinalOrdinal.Int (Ordinal.count l)
                                                    sub ordinalOrdinal.Int (Ordinal.count (List.tl (List.tl l)))
                                                    path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                    proof
                                                    detailed proof
                                                    ground_instances6
                                                    definitions0
                                                    inductions0
                                                    search_time
                                                    0.020s
                                                    details
                                                    Expand
                                                    smt_stats
                                                    arith offset eqs4
                                                    num checks14
                                                    arith assert lower27
                                                    arith pivots16
                                                    rlimit count5304
                                                    mk clause73
                                                    datatype occurs check45
                                                    mk bool var174
                                                    arith assert upper26
                                                    datatype splits11
                                                    decisions51
                                                    arith add rows37
                                                    arith bound prop5
                                                    propagations47
                                                    interface eqs1
                                                    conflicts18
                                                    arith fixed eqs23
                                                    datatype accessor ax11
                                                    minimized lits1
                                                    arith conflicts3
                                                    arith assert diseq3
                                                    datatype constructor ax21
                                                    num allocs19746264
                                                    final checks12
                                                    added eqs113
                                                    del clause21
                                                    arith eq adapter20
                                                    memory11.510000
                                                    max memory11.510000
                                                    Expand
                                                    • start[0.020s]
                                                        not (l <> [] && List.tl l = [])
                                                        && not (l = [])
                                                           && Ordinal.count l >= 0 && Ordinal.count (List.tl (List.tl l)) >= 0
                                                        ==> not
                                                            (not
                                                             ((List.tl (List.tl l)) <> [] && List.tl (List.tl (List.tl l)) = [])
                                                             && not (List.tl (List.tl l) = []))
                                                            || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl (List.tl l))))
                                                               (Ordinal.Int (Ordinal.count l))
                                                    • simplify
                                                      into
                                                      (not
                                                       (((not (l <> [] && List.tl l = []) && not (l = [])) && Ordinal.count l >= 0)
                                                        && Ordinal.count (List.tl (List.tl l)) >= 0)
                                                       || not
                                                          (not ((List.tl (List.tl l)) <> [] && List.tl (List.tl (List.tl l)) = [])
                                                           && not (List.tl (List.tl l) = [])))
                                                      || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl (List.tl l))))
                                                         (Ordinal.Int (Ordinal.count l))
                                                      expansions
                                                      []
                                                      rewrite_steps
                                                        forward_chaining
                                                        • unroll
                                                          expr
                                                          (let ((a!1 (|Ordinal.Int_93| (|count_`ty_0 list`_1134|
                                                                                         (|get.::.1_111…
                                                          expansions
                                                          • unroll
                                                            expr
                                                            (|count_`ty_0 list`_1134| (|get.::.1_1118| (|get.::.1_1118| l_1125)))
                                                            expansions
                                                            • unroll
                                                              expr
                                                              (|count_`ty_0 list`_1134| l_1125)
                                                              expansions
                                                              • unroll
                                                                expr
                                                                (|count_`ty_0 list`_1134|
                                                                  (|get.::.1_1118| (|get.::.1_1118| (|get.::.1_1118| l_1125))))
                                                                expansions
                                                                • unroll
                                                                  expr
                                                                  (let ((a!1 (|Ordinal.Int_93| (|count_`ty_0 list`_1134|
                                                                                                 (|get.::.1_111…
                                                                  expansions
                                                                  • unroll
                                                                    expr
                                                                    (|count_`ty_0 list`_1134| (|get.::.1_1118| l_1125))
                                                                    expansions
                                                                    • unsat
                                                                      (let ((a!1 (ite (>= (|count_`ty_0 list`_1134| (|get.::.1_1118| l_1125)) 0)
                                                                                      (|count_`…

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

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

                                                                    Defining Merge Sort

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

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

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

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

                                                                      (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                      • start[0.433s, "1"]
                                                                          (x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                      • induction on (functional odds)
                                                                        :scheme (not (not (x <> [] && List.tl x = []) && not (x = [])) ==> φ x)
                                                                                && (not (x = [])
                                                                                    && not (x <> [] && List.tl x = []) && φ (List.tl (List.tl x))
                                                                                    ==> φ x)
                                                                      • Split (((not (x <> [] && List.tl x = []) && not (x = [])
                                                                                 || not (not (x = []) && not (List.tl x = [])))
                                                                                || not (List.length x <= List.length (odds x)))
                                                                               && ((not
                                                                                    ((not (x = []) && not (x <> [] && List.tl x = []))
                                                                                     && (not
                                                                                         (not (List.tl (List.tl x) = [])
                                                                                          && not (List.tl (List.tl (List.tl x)) = []))
                                                                                         || not
                                                                                            (List.length (List.tl (List.tl x)) <=
                                                                                             List.length (odds (List.tl (List.tl x))))))
                                                                                    || not (not (x = []) && not (List.tl x = [])))
                                                                                   || not (List.length x <= List.length (odds x)))
                                                                               :cases [((x = [] || List.tl x = [])
                                                                                        || not (List.length x <= List.length (odds x)))
                                                                                       || not (x <> [] && List.tl x = []) && not (x = []);
                                                                                       (((x = [] || x <> [] && List.tl x = [])
                                                                                         || not
                                                                                            (not
                                                                                             (not (List.tl (List.tl x) = [])
                                                                                              && not (List.tl (List.tl (List.tl x)) = []))
                                                                                             || not
                                                                                                (List.length (List.tl (List.tl x)) <=
                                                                                                 List.length (odds (List.tl (List.tl x))))))
                                                                                        || List.tl x = [])
                                                                                       || not (List.length x <= List.length (odds x))])
                                                                        • subproof
                                                                          (((x = [] || x <> [] && List.tl x = []) || not (not (not (List.tl (List.tl x) = []) && not (List.tl (List.tl (List.tl x)) = [])) || not (List.length (List.tl (List.tl x)) <= List.length (odds (List.tl (List.tl x)))))) || List.tl x = []) || not (List.length x <= List.length (odds x))
                                                                          • start[0.432s, "1"]
                                                                              (((x = [] || x <> [] && List.tl x = [])
                                                                                || not
                                                                                   (not
                                                                                    (not (List.tl (List.tl x) = [])
                                                                                     && not (List.tl (List.tl (List.tl x)) = []))
                                                                                    || not
                                                                                       (List.length (List.tl (List.tl x)) <=
                                                                                        List.length (odds (List.tl (List.tl x))))))
                                                                               || List.tl x = [])
                                                                              || not (List.length x <= List.length (odds x))
                                                                          • simplify
                                                                            into
                                                                            ((((x = [] || List.tl x = []) || not (List.tl (List.tl x) = []))
                                                                              || not
                                                                                 (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))))
                                                                             && (((((x = [] || List.tl x = [])
                                                                                    || List.length (List.tl (List.tl x)) <=
                                                                                       List.length (odds (List.tl (List.tl x))))
                                                                                   || List.tl (List.tl x) = [])
                                                                                  || List.tl (List.tl (List.tl x)) = [])
                                                                                 || not
                                                                                    (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x))))))
                                                                            && ((((x = [] || List.tl x = []) || List.tl (List.tl x) = [])
                                                                                 || not (List.tl (List.tl (List.tl x)) = []))
                                                                                || not
                                                                                   (List.length (List.tl x) <= List.length (odds (List.tl (List.tl x)))))
                                                                            expansions
                                                                            [List.length, odds, List.length]
                                                                            rewrite_steps
                                                                              forward_chaining
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • List.len_nonnegative
                                                                              • Subproof
                                                                              • Subproof
                                                                              • Subproof
                                                                          • subproof
                                                                            ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x))) || not (x <> [] && List.tl x = []) && not (x = [])
                                                                            • start[0.432s, "2"]
                                                                                ((x = [] || List.tl x = []) || not (List.length x <= List.length (odds x)))
                                                                                || not (x <> [] && List.tl x = []) && not (x = [])
                                                                            • simplify
                                                                              into
                                                                              true
                                                                              expansions
                                                                              []
                                                                              rewrite_steps
                                                                                forward_chaining
                                                                                • List.len_nonnegative
                                                                                • List.len_nonnegative

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

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

                                                                        Termination proof

                                                                        call `merge_sort (odds l)` from `merge_sort l`
                                                                        originalmerge_sort l
                                                                        submerge_sort (odds l)
                                                                        original ordinalmerge_sort_measure l
                                                                        sub ordinalmerge_sort_measure (odds l)
                                                                        path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                                        proof
                                                                        detailed proof
                                                                        ground_instances1
                                                                        definitions0
                                                                        inductions0
                                                                        search_time
                                                                        0.013s
                                                                        details
                                                                        Expand
                                                                        smt_stats
                                                                        num checks3
                                                                        arith assert lower3
                                                                        arith pivots1
                                                                        rlimit count5065
                                                                        mk clause3
                                                                        datatype occurs check28
                                                                        mk bool var51
                                                                        datatype splits9
                                                                        decisions15
                                                                        propagations3
                                                                        conflicts8
                                                                        datatype accessor ax7
                                                                        datatype constructor ax13
                                                                        num allocs3803403140
                                                                        final checks6
                                                                        added eqs39
                                                                        del clause3
                                                                        memory39.090000
                                                                        max memory50.550000
                                                                        Expand
                                                                        • start[0.013s]
                                                                            not (l <> [] && List.tl l = [])
                                                                            && not (l = [])
                                                                               && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                  && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >=
                                                                                     0
                                                                            ==> not
                                                                                (not ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = []))
                                                                                && not
                                                                                   (not ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = []))
                                                                                || Ordinal.( << )
                                                                                   (Ordinal.Int
                                                                                    (if List.length (odds l) >= 0 then List.length (odds l) else 0))
                                                                                   (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                        • simplify
                                                                          into
                                                                          (not
                                                                           (((not (l <> [] && List.tl l = []) && not (l = []))
                                                                             && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                            && (if List.length (odds l) >= 0 then List.length (odds l) else 0) >= 0)
                                                                           || not (not ((odds l) <> [] && List.tl (odds l) = []) && not (odds l = [])))
                                                                          || Ordinal.( << )
                                                                             (Ordinal.Int
                                                                              (if List.length (odds l) >= 0 then List.length (odds l) else 0))
                                                                             (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                          expansions
                                                                          []
                                                                          rewrite_steps
                                                                            forward_chaining
                                                                            • unroll
                                                                              expr
                                                                              (let ((a!1 (ite (>= (|List.length_1400| (odds_1404 l_1410)) 0)
                                                                                              (|List.length_1400| (…
                                                                              expansions
                                                                              • unsat
                                                                                (let ((a!1 (and (not (= l_1410 |[]_2|))
                                                                                                (not (= (|get.::.1_1393| l_1410) |[]_2|))))
                                                                                …

                                                                              call `merge_sort (odds (List.tl l))` from `merge_sort l`
                                                                              originalmerge_sort l
                                                                              submerge_sort (odds (List.tl l))
                                                                              original ordinalmerge_sort_measure l
                                                                              sub ordinalmerge_sort_measure (odds (List.tl l))
                                                                              path[not (l <> [] && List.tl l = []) && not (l = [])]
                                                                              proof
                                                                              detailed proof
                                                                              ground_instances4
                                                                              definitions0
                                                                              inductions0
                                                                              search_time
                                                                              0.024s
                                                                              details
                                                                              Expand
                                                                              smt_stats
                                                                              num checks10
                                                                              arith assert lower6
                                                                              arith pivots6
                                                                              rlimit count3369
                                                                              mk clause16
                                                                              datatype occurs check83
                                                                              mk bool var121
                                                                              arith assert upper14
                                                                              datatype splits25
                                                                              decisions42
                                                                              arith add rows8
                                                                              propagations35
                                                                              conflicts15
                                                                              datatype accessor ax12
                                                                              arith conflicts1
                                                                              datatype constructor ax27
                                                                              num allocs3663285686
                                                                              final checks18
                                                                              added eqs100
                                                                              del clause8
                                                                              arith eq adapter2
                                                                              memory39.000000
                                                                              max memory50.550000
                                                                              Expand
                                                                              • start[0.024s]
                                                                                  not (l <> [] && List.tl l = [])
                                                                                  && not (l = [])
                                                                                     && (if List.length l >= 0 then List.length l else 0) >= 0
                                                                                        && (if List.length (odds (List.tl l)) >= 0
                                                                                            then List.length (odds (List.tl l)) else 0)
                                                                                           >= 0
                                                                                  ==> not
                                                                                      (not ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                       && not (odds (List.tl l) = []))
                                                                                      && not
                                                                                         (not ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                          && not (odds (List.tl l) = []))
                                                                                      || Ordinal.( << )
                                                                                         (Ordinal.Int
                                                                                          (if List.length (odds (List.tl l)) >= 0
                                                                                           then List.length (odds (List.tl l)) else 0))
                                                                                         (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                              • simplify
                                                                                into
                                                                                (not
                                                                                 (((not (l <> [] && List.tl l = []) && not (l = []))
                                                                                   && (if List.length l >= 0 then List.length l else 0) >= 0)
                                                                                  && (if List.length (odds (List.tl l)) >= 0
                                                                                      then List.length (odds (List.tl l)) else 0)
                                                                                     >= 0)
                                                                                 || not
                                                                                    (not ((odds (List.tl l)) <> [] && List.tl (odds (List.tl l)) = [])
                                                                                     && not (odds (List.tl l) = [])))
                                                                                || Ordinal.( << )
                                                                                   (Ordinal.Int
                                                                                    (if List.length (odds (List.tl l)) >= 0
                                                                                     then List.length (odds (List.tl l)) else 0))
                                                                                   (Ordinal.Int (if List.length l >= 0 then List.length l else 0))
                                                                                expansions
                                                                                []
                                                                                rewrite_steps
                                                                                  forward_chaining
                                                                                  • unroll
                                                                                    expr
                                                                                    (let ((a!1 (>= (|List.length_1400| (odds_1404 (|get.::.1_1393| l_1410))) 0))
                                                                                          (a!3 (|Ordinal.In…
                                                                                    expansions
                                                                                    • unroll
                                                                                      expr
                                                                                      (odds_1404 (|get.::.1_1393| l_1410))
                                                                                      expansions
                                                                                      • unroll
                                                                                        expr
                                                                                        (|List.length_1400| (odds_1404 (|get.::.1_1393| l_1410)))
                                                                                        expansions
                                                                                        • unroll
                                                                                          expr
                                                                                          (|List.length_1400| l_1410)
                                                                                          expansions
                                                                                          • unsat
                                                                                            (let ((a!1 (not (and ((_ is (|::_3| (Int |`int list`_1391|) |`int list`_1391|))
                                                                                                                …

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

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

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

                                                                                          Proving Merge Sort correct

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

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

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

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

                                                                                          Termination proof

                                                                                          call `is_sorted (List.tl x)` from `is_sorted x`
                                                                                          originalis_sorted x
                                                                                          subis_sorted (List.tl x)
                                                                                          original ordinalOrdinal.Int (Ordinal.count x)
                                                                                          sub ordinalOrdinal.Int (Ordinal.count (List.tl x))
                                                                                          path[List.hd x <= List.hd (List.tl x) && not (x <> [] && List.tl x = []) && not (x = [])]
                                                                                          proof
                                                                                          detailed proof
                                                                                          ground_instances3
                                                                                          definitions0
                                                                                          inductions0
                                                                                          search_time
                                                                                          0.015s
                                                                                          details
                                                                                          Expand
                                                                                          smt_stats
                                                                                          num checks8
                                                                                          arith assert lower26
                                                                                          arith pivots9
                                                                                          rlimit count2914
                                                                                          mk clause32
                                                                                          datatype occurs check34
                                                                                          mk bool var109
                                                                                          arith assert upper16
                                                                                          datatype splits11
                                                                                          decisions23
                                                                                          arith add rows17
                                                                                          arith bound prop1
                                                                                          propagations24
                                                                                          interface eqs3
                                                                                          conflicts11
                                                                                          arith fixed eqs12
                                                                                          datatype accessor ax6
                                                                                          arith conflicts2
                                                                                          arith assert diseq2
                                                                                          datatype constructor ax10
                                                                                          num allocs3897233446
                                                                                          final checks12
                                                                                          added eqs67
                                                                                          del clause16
                                                                                          arith eq adapter16
                                                                                          memory42.720000
                                                                                          max memory50.550000
                                                                                          Expand
                                                                                          • start[0.015s]
                                                                                              List.hd x <= List.hd (List.tl x)
                                                                                              && not (x <> [] && List.tl x = [])
                                                                                                 && not (x = [])
                                                                                                    && Ordinal.count x >= 0 && Ordinal.count (List.tl x) >= 0
                                                                                              ==> not
                                                                                                  (List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                   && not ((List.tl x) <> [] && List.tl (List.tl x) = [])
                                                                                                      && not (List.tl x = []))
                                                                                                  || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                                     (Ordinal.Int (Ordinal.count x))
                                                                                          • simplify
                                                                                            into
                                                                                            (not
                                                                                             ((((List.hd x <= List.hd (List.tl x) && not (x <> [] && List.tl x = []))
                                                                                                && not (x = []))
                                                                                               && Ordinal.count x >= 0)
                                                                                              && Ordinal.count (List.tl x) >= 0)
                                                                                             || not
                                                                                                ((List.hd (List.tl x) <= List.hd (List.tl (List.tl x))
                                                                                                  && not ((List.tl x) <> [] && List.tl (List.tl x) = []))
                                                                                                 && not (List.tl x = [])))
                                                                                            || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl x)))
                                                                                               (Ordinal.Int (Ordinal.count x))
                                                                                            expansions
                                                                                            []
                                                                                            rewrite_steps
                                                                                              forward_chaining
                                                                                              • unroll
                                                                                                expr
                                                                                                (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`int list`_1435|
                                                                                                                                      (…
                                                                                                expansions
                                                                                                • unroll
                                                                                                  expr
                                                                                                  (|count_`int list`_1435| (|get.::.1_1425| x_1426))
                                                                                                  expansions
                                                                                                  • unroll
                                                                                                    expr
                                                                                                    (|count_`int list`_1435| x_1426)
                                                                                                    expansions
                                                                                                    • unsat
                                                                                                      (let ((a!1 (>= (ite (>= (|get.::.0_1424| x_1426) 0) (|get.::.0_1424| x_1426) 0)
                                                                                                                     0))
                                                                                                       …

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

                                                                                                    In [15]:
                                                                                                    is_sorted [1;2;3;4;5]
                                                                                                    
                                                                                                    Out[15]:
                                                                                                    - : bool = true
                                                                                                    
                                                                                                    In [16]:
                                                                                                    is_sorted [1;4;2]
                                                                                                    
                                                                                                    Out[16]:
                                                                                                    - : bool = false
                                                                                                    
                                                                                                    In [17]:
                                                                                                    is_sorted [1]
                                                                                                    
                                                                                                    Out[17]:
                                                                                                    - : bool = true
                                                                                                    
                                                                                                    In [18]:
                                                                                                    instance (fun x -> List.length x >= 5 && is_sorted x)
                                                                                                    
                                                                                                    Out[18]:
                                                                                                    - : int list -> bool = <fun>
                                                                                                    module CX : sig val x : int list end
                                                                                                    
                                                                                                    Instance (after 11 steps, 0.021s):
                                                                                                     let (x : int list) = [7719; 7719; 16574; 18856; 24709]
                                                                                                    
                                                                                                    Instance
                                                                                                    proof attempt
                                                                                                    ground_instances11
                                                                                                    definitions0
                                                                                                    inductions0
                                                                                                    search_time
                                                                                                    0.021s
                                                                                                    details
                                                                                                    Expand
                                                                                                    smt_stats
                                                                                                    num checks23
                                                                                                    arith assert lower60
                                                                                                    arith pivots27
                                                                                                    rlimit count8731
                                                                                                    mk clause104
                                                                                                    datatype occurs check69
                                                                                                    mk bool var315
                                                                                                    arith assert upper38
                                                                                                    datatype splits35
                                                                                                    decisions94
                                                                                                    arith add rows128
                                                                                                    propagations201
                                                                                                    interface eqs1
                                                                                                    conflicts36
                                                                                                    arith fixed eqs35
                                                                                                    datatype accessor ax24
                                                                                                    arith conflicts11
                                                                                                    arith assert diseq10
                                                                                                    datatype constructor ax42
                                                                                                    num allocs4055757109
                                                                                                    final checks36
                                                                                                    added eqs307
                                                                                                    del clause72
                                                                                                    arith eq adapter38
                                                                                                    memory43.470000
                                                                                                    max memory50.550000
                                                                                                    Expand
                                                                                                    • start[0.021s] List.length :var_0: >= 5 && is_sorted :var_0:
                                                                                                    • unroll
                                                                                                      expr
                                                                                                      (is_sorted_41 x_46)
                                                                                                      expansions
                                                                                                      • unroll
                                                                                                        expr
                                                                                                        (|List.length_1442| x_46)
                                                                                                        expansions
                                                                                                        • unroll
                                                                                                          expr
                                                                                                          (|List.length_1442| (|get.::.1_1441| x_46))
                                                                                                          expansions
                                                                                                          • unroll
                                                                                                            expr
                                                                                                            (|List.length_1442| (|get.::.1_1441| (|get.::.1_1441| x_46)))
                                                                                                            expansions
                                                                                                            • unroll
                                                                                                              expr
                                                                                                              (is_sorted_41 (|get.::.1_1441| x_46))
                                                                                                              expansions
                                                                                                              • unroll
                                                                                                                expr
                                                                                                                (|List.length_1442| (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| x_46))))
                                                                                                                expansions
                                                                                                                • unroll
                                                                                                                  expr
                                                                                                                  (is_sorted_41 (|get.::.1_1441| (|get.::.1_1441| x_46)))
                                                                                                                  expansions
                                                                                                                  • unroll
                                                                                                                    expr
                                                                                                                    (let ((a!1 (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| x_46))))))
                                                                                                                      (|List.l…
                                                                                                                    expansions
                                                                                                                    • unroll
                                                                                                                      expr
                                                                                                                      (is_sorted_41 (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| x_46))))
                                                                                                                      expansions
                                                                                                                      • unroll
                                                                                                                        expr
                                                                                                                        (let ((a!1 (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| x_46))))))
                                                                                                                          (|List.l…
                                                                                                                        expansions
                                                                                                                        • unroll
                                                                                                                          expr
                                                                                                                          (let ((a!1 (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| (|get.::.1_1441| x_46))))))
                                                                                                                            (is_sort…
                                                                                                                          expansions
                                                                                                                          • Sat (Some let (x : int list) = [7719; 7719; 16574; 18856; 24709] )
                                                                                                                          In [19]:
                                                                                                                          instance (fun x -> List.length x >= 5 && is_sorted x && is_sorted (List.rev x))
                                                                                                                          
                                                                                                                          Out[19]:
                                                                                                                          - : int list -> bool = <fun>
                                                                                                                          module CX : sig val x : int list end
                                                                                                                          
                                                                                                                          Instance (after 44 steps, 0.119s):
                                                                                                                           let (x : int list) = [1733; 1733; 1733; 1733; 1733]
                                                                                                                          
                                                                                                                          Instance
                                                                                                                          proof attempt
                                                                                                                          ground_instances44
                                                                                                                          definitions0
                                                                                                                          inductions0
                                                                                                                          search_time
                                                                                                                          0.119s
                                                                                                                          details
                                                                                                                          Expand
                                                                                                                          smt_stats
                                                                                                                          arith offset eqs158
                                                                                                                          num checks89
                                                                                                                          arith assert lower563
                                                                                                                          arith pivots391
                                                                                                                          rlimit count107941
                                                                                                                          mk clause1094
                                                                                                                          datatype occurs check2466
                                                                                                                          mk bool var5164
                                                                                                                          arith assert upper664
                                                                                                                          datatype splits1056
                                                                                                                          decisions2445
                                                                                                                          arith add rows2041
                                                                                                                          arith bound prop34
                                                                                                                          propagations6197
                                                                                                                          interface eqs98
                                                                                                                          conflicts214
                                                                                                                          arith fixed eqs480
                                                                                                                          datatype accessor ax760
                                                                                                                          minimized lits67
                                                                                                                          arith conflicts32
                                                                                                                          arith assert diseq138
                                                                                                                          datatype constructor ax1035
                                                                                                                          final checks288
                                                                                                                          added eqs11649
                                                                                                                          del clause848
                                                                                                                          arith eq adapter554
                                                                                                                          memory41.780000
                                                                                                                          max memory50.550000
                                                                                                                          num allocs4313374063.000000
                                                                                                                          Expand
                                                                                                                          • start[0.119s]
                                                                                                                              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_1455| x_48)
                                                                                                                                expansions
                                                                                                                                • unroll
                                                                                                                                  expr
                                                                                                                                  (is_sorted_41 (|List.rev_1455| x_48))
                                                                                                                                  expansions
                                                                                                                                  • unroll
                                                                                                                                    expr
                                                                                                                                    (is_sorted_41 x_48)
                                                                                                                                    expansions
                                                                                                                                    • unroll
                                                                                                                                      expr
                                                                                                                                      (|List.length_1452| x_48)
                                                                                                                                      expansions
                                                                                                                                      • unroll
                                                                                                                                        expr
                                                                                                                                        (|List.rev_1455| (|get.::.1_1451| x_48))
                                                                                                                                        expansions
                                                                                                                                        • unroll
                                                                                                                                          expr
                                                                                                                                          (|List.append_1459|
                                                                                                                                            (|List.rev_1455| (|get.::.1_1451| x_48))
                                                                                                                                            (|::_3| (|get.::.0_1450| x_48) |[]_…
                                                                                                                                          expansions
                                                                                                                                          • unroll
                                                                                                                                            expr
                                                                                                                                            (|List.length_1452| (|get.::.1_1451| x_48))
                                                                                                                                            expansions
                                                                                                                                            • unroll
                                                                                                                                              expr
                                                                                                                                              (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48)))
                                                                                                                                              expansions
                                                                                                                                              • unroll
                                                                                                                                                expr
                                                                                                                                                (|List.append_1459|
                                                                                                                                                  (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48)))
                                                                                                                                                  (|::_3| (|get.::.…
                                                                                                                                                expansions
                                                                                                                                                • unroll
                                                                                                                                                  expr
                                                                                                                                                  (is_sorted_41 (|get.::.1_1451| (|List.rev_1455| x_48)))
                                                                                                                                                  expansions
                                                                                                                                                  • unroll
                                                                                                                                                    expr
                                                                                                                                                    (|List.length_1452| (|get.::.1_1451| (|get.::.1_1451| x_48)))
                                                                                                                                                    expansions
                                                                                                                                                    • unroll
                                                                                                                                                      expr
                                                                                                                                                      (is_sorted_41 (|get.::.1_1451| x_48))
                                                                                                                                                      expansions
                                                                                                                                                      • unroll
                                                                                                                                                        expr
                                                                                                                                                        (|List.append_1459|
                                                                                                                                                          (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| x_48)))
                                                                                                                                                          (|::_3| (|get.::.…
                                                                                                                                                        expansions
                                                                                                                                                        • unroll
                                                                                                                                                          expr
                                                                                                                                                          (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))
                                                                                                                                                          expansions
                                                                                                                                                          • unroll
                                                                                                                                                            expr
                                                                                                                                                            (let ((a!1 (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                  (a!2 …
                                                                                                                                                            expansions
                                                                                                                                                            • unroll
                                                                                                                                                              expr
                                                                                                                                                              (|List.length_1452| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))
                                                                                                                                                              expansions
                                                                                                                                                              • unroll
                                                                                                                                                                expr
                                                                                                                                                                (is_sorted_41 (|get.::.1_1451| (|get.::.1_1451| x_48)))
                                                                                                                                                                expansions
                                                                                                                                                                • unroll
                                                                                                                                                                  expr
                                                                                                                                                                  (let ((a!1 (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                    (|List.a…
                                                                                                                                                                  expansions
                                                                                                                                                                  • unroll
                                                                                                                                                                    expr
                                                                                                                                                                    (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| x_48))))))
                                                                                                                                                                      (|List.a…
                                                                                                                                                                    expansions
                                                                                                                                                                    • unroll
                                                                                                                                                                      expr
                                                                                                                                                                      (is_sorted_41 (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| x_48))))
                                                                                                                                                                      expansions
                                                                                                                                                                      • unroll
                                                                                                                                                                        expr
                                                                                                                                                                        (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                          (|List.r…
                                                                                                                                                                        expansions
                                                                                                                                                                        • unroll
                                                                                                                                                                          expr
                                                                                                                                                                          (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                (a!2 …
                                                                                                                                                                          expansions
                                                                                                                                                                          • unroll
                                                                                                                                                                            expr
                                                                                                                                                                            (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                              (|List.l…
                                                                                                                                                                            expansions
                                                                                                                                                                            • unroll
                                                                                                                                                                              expr
                                                                                                                                                                              (is_sorted_41 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))
                                                                                                                                                                              expansions
                                                                                                                                                                              • unroll
                                                                                                                                                                                expr
                                                                                                                                                                                (let ((a!1 (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                expansions
                                                                                                                                                                                • unroll
                                                                                                                                                                                  expr
                                                                                                                                                                                  (let ((a!1 (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                  expansions
                                                                                                                                                                                  • unroll
                                                                                                                                                                                    expr
                                                                                                                                                                                    (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                      (|List.r…
                                                                                                                                                                                    expansions
                                                                                                                                                                                    • unroll
                                                                                                                                                                                      expr
                                                                                                                                                                                      (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                      expansions
                                                                                                                                                                                      • unroll
                                                                                                                                                                                        expr
                                                                                                                                                                                        (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                          (|List.l…
                                                                                                                                                                                        expansions
                                                                                                                                                                                        • unroll
                                                                                                                                                                                          expr
                                                                                                                                                                                          (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                            (|List.a…
                                                                                                                                                                                          expansions
                                                                                                                                                                                          • unroll
                                                                                                                                                                                            expr
                                                                                                                                                                                            (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                              (is_sort…
                                                                                                                                                                                            expansions
                                                                                                                                                                                            • unroll
                                                                                                                                                                                              expr
                                                                                                                                                                                              (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                                    (a!2 …
                                                                                                                                                                                              expansions
                                                                                                                                                                                              • unroll
                                                                                                                                                                                                expr
                                                                                                                                                                                                (let ((a!1 (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                                expansions
                                                                                                                                                                                                • unroll
                                                                                                                                                                                                  expr
                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                                  expansions
                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                    expr
                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| x_48))))))
                                                                                                                                                                                                      (is_sort…
                                                                                                                                                                                                    expansions
                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                      expr
                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                        (|List.a…
                                                                                                                                                                                                      expansions
                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                        expr
                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                          (|List.r…
                                                                                                                                                                                                        expansions
                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                          expr
                                                                                                                                                                                                          (let ((a!1 (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                                                (a!2 …
                                                                                                                                                                                                          expansions
                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                            expr
                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1451| (|List.rev_1455| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                              (|List.a…
                                                                                                                                                                                                            expansions
                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                              expr
                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                                (|List.a…
                                                                                                                                                                                                              expansions
                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                expr
                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48)))))
                                                                                                                                                                                                                      (a!2 …
                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                                    (|List.a…
                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| x_48))))))
                                                                                                                                                                                                                      (|List.l…
                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1451| (|get.::.1_1451| (|get.::.1_1451| (|List.rev_1455| x_48))))))
                                                                                                                                                                                                                        (is_sort…
                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                      • Sat (Some let (x : int list) = [1733; 1733; 1733; 1733; 1733] )

                                                                                                                                                                                                                      Proving Merge Sort sorts

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

                                                                                                                                                                                                                      We can write this this way:

                                                                                                                                                                                                                      theorem merge_sort_sorts x =
                                                                                                                                                                                                                       is_sorted (merge_sort x)
                                                                                                                                                                                                                      

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

                                                                                                                                                                                                                      In [20]:
                                                                                                                                                                                                                      verify (fun x -> is_sorted (merge_sort x))
                                                                                                                                                                                                                      
                                                                                                                                                                                                                      Out[20]:
                                                                                                                                                                                                                      - : int list -> bool = <fun>
                                                                                                                                                                                                                      
                                                                                                                                                                                                                      Unknown (Verified up to bound 100)
                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                      expanded
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl x)))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds x))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds x)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds x)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl x))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds x))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds x)))))
                                                                                                                                                                                                                      • odds (odds (odds x))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds x)))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds x)
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else …) else …)
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (List.tl (merge_sort x))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl x)))
                                                                                                                                                                                                                      • is_sorted (List.tl (merge_sort x))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (odds x)
                                                                                                                                                                                                                      • odds (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 (List.tl (List.tl x)))
                                                                                                                                                                                                                      • merge (merge_sort (odds x)) (merge_sort (odds (List.tl x)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl x)))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl x))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl x))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort x
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds x))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds x)))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (odds (List.tl x))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl x))))
                                                                                                                                                                                                                      • odds x
                                                                                                                                                                                                                      • odds (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds x))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (merge_sort x)))
                                                                                                                                                                                                                      • is_sorted (merge_sort x)
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl x)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds x)))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl x))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl x)))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x))))
                                                                                                                                                                                                                      • odds (List.tl x)
                                                                                                                                                                                                                      • odds (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds x)))
                                                                                                                                                                                                                      blocked
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else …) else …)
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x)))))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x)))))))
                                                                                                                                                                                                                      • odds (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds x)))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (odds x))))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (List.tl x))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x))))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (List.tl (odds …)))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) else if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) else if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else merge_sort (odds (List.tl x))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then List.tl (merge_sort (odds (List.tl x))) else (merge_sort (odds (List.tl x)))) <= List.hd (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))) then if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else List.tl (merge_sort (odds x)) else (List.tl (if List.hd (merge_sort (odds (List.tl x))) <= List.hd (merge_sort (odds x)) then merge_sort (odds x) else (List.tl (merge_sort (odds x)))))) then … else …) then … else …) …
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (odds (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds x))))))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (odds (odds (odds …)))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (odds (List.tl (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl (odds x))))))))
                                                                                                                                                                                                                      • odds (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x))))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (List.tl (odds (odds …))))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (odds …)))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (odds (List.tl x)))))))))
                                                                                                                                                                                                                      • merge (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) else (List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))))) (if List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else merge_sort (odds (List.tl (odds …)))) <= List.hd (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else List.tl (merge_sort (odds (odds …))) else (List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))))) then List.tl (if List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) <= List.hd (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) then List.tl (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …))))) else …) else …)
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (odds (odds (List.tl (odds …))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (odds (odds …))))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (odds …)))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • is_sorted (List.tl (List.tl (List.tl (List.tl (merge_sort x)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • merge_sort (odds (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl x)))))))
                                                                                                                                                                                                                      • merge_sort (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (odds …))))
                                                                                                                                                                                                                      • odds (odds (List.tl (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl (List.tl x)))))))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (merge_sort (odds (odds …))) (merge_sort (odds (List.tl (odds …))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (List.tl (List.tl (odds (List.tl (odds (List.tl (odds …))))))))
                                                                                                                                                                                                                      • merge (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then merge_sort (odds (odds …)) else (List.tl (merge_sort (odds (odds …))))) (if List.hd (merge_sort (odds (List.tl (odds …)))) <= List.hd (merge_sort (odds (odds …))) then List.tl (merge_sort (odds (List.tl (odds …)))) else (merge_sort (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      • odds (List.tl (odds (odds (List.tl (odds …)))))
                                                                                                                                                                                                                      proof attempt
                                                                                                                                                                                                                      ground_instances100
                                                                                                                                                                                                                      definitions0
                                                                                                                                                                                                                      inductions0
                                                                                                                                                                                                                      search_time
                                                                                                                                                                                                                      2.421s
                                                                                                                                                                                                                      Expand
                                                                                                                                                                                                                      • start[2.421s] is_sorted (merge_sort :var_0:)
                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                        (merge_sort_37 x_50)
                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                          (is_sorted_41 (merge_sort_37 x_50))
                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                            (odds_1473 (|get.::.1_1472| x_50))
                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                              (merge_sort_37 (odds_1473 (|get.::.1_1472| x_50)))
                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                (odds_1473 x_50)
                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                  (merge_sort_37 (odds_1473 x_50))
                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                    (merge_14 (merge_sort_37 (odds_1473 x_50))
                                                                                                                                                                                                                                              (merge_sort_37 (odds_1473 (|get.::.1_1472| x_50…
                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                      (odds_1473 (|get.::.1_1472| (|get.::.1_1472| x_50)))
                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                        (odds_1473 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| x_50))))
                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                          (is_sorted_41 (|get.::.1_1472| (merge_sort_37 x_50)))
                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                            (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))
                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                              (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                (merge_sort_37 a!1))
                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                (odds_1473 (odds_1473 (|get.::.1_1472| x_50)))
                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                  (let ((a!1 (merge_sort_37 (odds_1473 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                        (a!2 (odds_1473 (|g…
                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                    (merge_sort_37 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))
                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.0_1471| (merge_sort_37 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                            (a!4 (|get.::…
                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                        (odds_1473 (|get.::.1_1472| (odds_1473 x_50)))
                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                          (merge_sort_37 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))
                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                            (odds_1473 (odds_1473 x_50))
                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                              (merge_sort_37 (odds_1473 (odds_1473 x_50)))
                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                (let ((a!1 (merge_sort_37 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                  (merge_14 (merge_sort_…
                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                    (odds_1473 a!1…
                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                      (odds_14…
                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.0_1471| (merge_sort_37 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                            (a!3 (|get.::…
                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                          (odds_14…
                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                          (odds_1473 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 x_50))))
                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                                  (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                (odds_1473 a!1…
                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                  (odds_1473 a!1))
                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                  (is_sorted_41 (|get.::.1_1472| (|get.::.1_1472| (merge_sort_37 x_50))))
                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                      (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))
                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                          (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                (a!2 (|get.::.1_1472| (…
                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                              (odds_1473 (|g…
                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                              (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))
                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                  (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                  (odds_1473 (odds_1473 (odds_1473 x_50)))
                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                    (merge_sort_37 (odds_1473 (odds_1473 (odds_1473 x_50))))
                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                        (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                        (let ((a!1 (merge_sort_37 (odds_1473 (odds_1473 (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                              (a!2 (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                          (let ((a!1 (merge_sort_37 (odds_1473 (|get.::.1_1472| (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                                (a!2 (|get.::.0_147…
                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                              (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                  (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))
                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                      (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                                                                            (a!2 (|get.::.1_1472| (…
                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.0_1471| (merge_sort_37 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                                                                              (a!3 (|get.::…
                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                            (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (merge_sort_37 x_50))))))
                                                                                                                                                                                                                                                                                                                              (is_sorted…
                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                  (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                    (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                        (merge_14 (merge_sor…
                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                          (odds_14…
                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                            (odds_1473 (|g…
                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                              (odds_14…
                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                (odds_1473 (|g…
                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                  (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                    (odds_1473 (|get.::.1_1472…
                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                        (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                                                                                                              (a!2 (merge_sort_…
                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                            (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                              (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1473 (|get.::.1_1472| (odds_1473 (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                    (a!2 (merge_sort_37 (od…
                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (merge_sort_37 (odds_1473 (|get.::.1_1472| (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                      (a!2 (|get.::.0_147…
                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                    (odds_1473 (|g…
                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                      (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                        (odds_1473 (odds_1473 (odds_1473 (odds_1473 x_50))))
                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_37 a!1))
                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                              (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                    (a!2 (|get.::.1_1472| (odds_1…
                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                  (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                    (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1472| (|get.::.1_1472| (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                      (odds_1473 (|g…
                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                          (odds_1473 (|get.::.…
                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                            (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                              (odds_1473 (odds_147…
                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                (odds_1473 (odds_147…
                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                  (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                    (odds_1473 (|get.::.1_1472…
                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (merge_sort_37 (odds…
                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!2 (merge_sort…
                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                              (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                              • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                expr
                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (odds_1473 (odds_1473 (odds_1473 (|get.::.1_1472| x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                  (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                  expr
                                                                                                                                                                                                                                                                                                                                                                                                                  (let ((a!1 (|get.::.1_1472| (odds_1473 (odds_1473 (|get.::.1_1472| x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (a!2 (odds_1473 (…
                                                                                                                                                                                                                                                                                                                                                                                                                  expansions
                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                    (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                      (odds_1473 (|get.::.1_1472…
                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                      (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                        (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                        (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                          (odds_1473 a!1))
                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (|get.::.1_1472| (odds_1473 (|get.::.1_1472| (odds_1473 x_50)))))
                                                                                                                                                                                                                                                                                                                                                                                                                                (a!2 (odds_1473 (…
                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                            (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                              (merge_sort_37 (odds_1473 …
                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                              (let ((a!1 (odds_1473 (odds_1473 (|get.::.1_1472| (odds_1473 x_50))))))
                                                                                                                                                                                                                                                                                                                                                                                                                                (merge_14 (merge_sort_37 (…
                                                                                                                                                                                                                                                                                                                                                                                                                              expansions

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

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

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

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

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                              In [23]:
                                                                                                                                                                                                                                                                                                                                                                                                                              #max_induct 2;;
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              theorem merge_sorts x y =
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted x && is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               ==>
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                              [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Out[23]:
                                                                                                                                                                                                                                                                                                                                                                                                                              val merge_sorts : int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                              Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              is_sorted x && is_sorted y ==> is_sorted (merge x y).
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                   && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                                   ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                  && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                      ==> φ y x).
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted x && is_sorted (List.tl y) ==> is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                              following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. (List.tl y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H7. List.hd y <= List.hd (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H8. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But we verify Subgoal 2.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. List.tl y = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. (merge x (List.tl y)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. List.hd y <= List.hd (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted (List.tl x) && is_sorted y ==> is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. is_sorted x
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              This simplifies, using the definitions of is_sorted and merge to the
                                                                                                                                                                                                                                                                                                                                                                                                                              following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. List.hd x <= List.hd (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                               H6. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H7. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But we verify Subgoal 1.3 by recursive unrolling.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H1. y <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H2. List.tl x = []
                                                                                                                                                                                                                                                                                                                                                                                                                               H3. is_sorted y
                                                                                                                                                                                                                                                                                                                                                                                                                               H4. (merge (List.tl x) y) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                               H5. List.hd x <= List.hd (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                               C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                               C1. is_sorted (merge (List.tl x) y)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              But simplification reduces this to true, using the definition of merge.
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                               Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def is_sorted)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                  (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              
                                                                                                                                                                                                                                                                                                                                                                                                                              Proved
                                                                                                                                                                                                                                                                                                                                                                                                                              proof
                                                                                                                                                                                                                                                                                                                                                                                                                              ground_instances6
                                                                                                                                                                                                                                                                                                                                                                                                                              definitions21
                                                                                                                                                                                                                                                                                                                                                                                                                              inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                              search_time
                                                                                                                                                                                                                                                                                                                                                                                                                              1.240s
                                                                                                                                                                                                                                                                                                                                                                                                                              details
                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                              smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                              num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                              arith assert lower4
                                                                                                                                                                                                                                                                                                                                                                                                                              arith pivots4
                                                                                                                                                                                                                                                                                                                                                                                                                              rlimit count112702
                                                                                                                                                                                                                                                                                                                                                                                                                              mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype occurs check14
                                                                                                                                                                                                                                                                                                                                                                                                                              mk bool var79
                                                                                                                                                                                                                                                                                                                                                                                                                              arith assert upper9
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype splits3
                                                                                                                                                                                                                                                                                                                                                                                                                              decisions29
                                                                                                                                                                                                                                                                                                                                                                                                                              arith add rows13
                                                                                                                                                                                                                                                                                                                                                                                                                              propagations29
                                                                                                                                                                                                                                                                                                                                                                                                                              conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype accessor ax8
                                                                                                                                                                                                                                                                                                                                                                                                                              arith conflicts2
                                                                                                                                                                                                                                                                                                                                                                                                                              arith assert diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                              datatype constructor ax10
                                                                                                                                                                                                                                                                                                                                                                                                                              final checks4
                                                                                                                                                                                                                                                                                                                                                                                                                              added eqs72
                                                                                                                                                                                                                                                                                                                                                                                                                              del clause4
                                                                                                                                                                                                                                                                                                                                                                                                                              arith eq adapter5
                                                                                                                                                                                                                                                                                                                                                                                                                              memory93.670000
                                                                                                                                                                                                                                                                                                                                                                                                                              max memory103.390000
                                                                                                                                                                                                                                                                                                                                                                                                                              num allocs43567666165.000000
                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                              • start[1.240s, "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.240s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                    (not (is_sorted x) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                  :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                          && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (List.hd x < List.hd y) && φ (List.tl y) x
                                                                                                                                                                                                                                                                                                                                                                                                                                              ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                             && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                 && not (y = []) && List.hd x < List.hd y && φ y (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                 ==> φ y x)
                                                                                                                                                                                                                                                                                                                                                                                                                                • Split ((((not
                                                                                                                                                                                                                                                                                                                                                                                                                                            (not
                                                                                                                                                                                                                                                                                                                                                                                                                                             ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                             && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || not (is_sorted x && is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                          && ((not
                                                                                                                                                                                                                                                                                                                                                                                                                                               (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                && (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not (is_sorted x && is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || is_sorted (merge x y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                         && ((not
                                                                                                                                                                                                                                                                                                                                                                                                                                              (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               && (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted x && is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || is_sorted (merge x y))
                                                                                                                                                                                                                                                                                                                                                                                                                                         :cases [((((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y);
                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || is_sorted (merge x y)])
                                                                                                                                                                                                                                                                                                                                                                                                                                  • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                    (((((x = [] || y = []) || List.hd y <= List.hd x) || not (not (is_sorted (List.tl x) && is_sorted y) || is_sorted (merge (List.tl x) y))) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[1.238s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                        (((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not
                                                                                                                                                                                                                                                                                                                                                                                                                                              (not (is_sorted (List.tl x) && is_sorted y)
                                                                                                                                                                                                                                                                                                                                                                                                                                               || is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                        || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                      ((((((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                           || not (List.hd x <= List.hd (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                         || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                        || List.hd x <= List.hd (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                       && ((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                           || List.hd x <= List.hd (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                      && (((((((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.tl x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge (List.tl x) y))
                                                                                                                                                                                                                                                                                                                                                                                                                                           || merge (List.tl x) y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                          || not (List.hd x <= List.hd (merge (List.tl x) y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                      [merge, is_sorted, is_sorted, merge, is_sorted, is_sorted, is_sorted, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                      • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                        (((((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (not (is_sorted x && is_sorted (List.tl y)) || is_sorted (merge x (List.tl y)))) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[1.238s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                            (((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                  (not (is_sorted x && is_sorted (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                            || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                        • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                          into
                                                                                                                                                                                                                                                                                                                                                                                                                                          ((((((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || not (is_sorted (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || List.tl y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.hd y <= List.hd (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                             || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                            || List.hd y <= List.hd (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                           && ((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                               || List.hd y <= List.hd (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                          && (((((((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (merge x (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                               || merge x (List.tl y) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                              || not (List.hd y <= List.hd (merge x (List.tl y))))
                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                          [merge, is_sorted, is_sorted, merge, is_sorted, is_sorted, is_sorted, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                          rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                            forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                              • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                          • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                            ((((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []) || (List.hd y <= List.hd x && not (y = [])) && not (x = [])) || not (is_sorted x)) || not (is_sorted y)) || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • start[1.238s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                ((((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                   || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                  || not (is_sorted x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not (is_sorted y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                || is_sorted (merge x y)
                                                                                                                                                                                                                                                                                                                                                                                                                                            • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                              into
                                                                                                                                                                                                                                                                                                                                                                                                                                              true
                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                              merge
                                                                                                                                                                                                                                                                                                                                                                                                                                              rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                forward_chaining

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

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Merge Sort contains the right elements

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    What does this mean, and why does it matter?

                                                                                                                                                                                                                                                                                                                                                                                                                                                    An incorrect sorting function

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Multiset equivalence

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

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                    Termination proof

                                                                                                                                                                                                                                                                                                                                                                                                                                                    call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                    originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                    subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                    sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    path[y <> [] && List.hd y = x && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                    0.014s
                                                                                                                                                                                                                                                                                                                                                                                                                                                    details
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                    smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                    num checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert lower8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith pivots5
                                                                                                                                                                                                                                                                                                                                                                                                                                                    rlimit count4680
                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk clause28
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype occurs check29
                                                                                                                                                                                                                                                                                                                                                                                                                                                    mk bool var88
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert upper11
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                    decisions23
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith add rows11
                                                                                                                                                                                                                                                                                                                                                                                                                                                    propagations45
                                                                                                                                                                                                                                                                                                                                                                                                                                                    conflicts10
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith fixed eqs8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype accessor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith assert diseq1
                                                                                                                                                                                                                                                                                                                                                                                                                                                    datatype constructor ax12
                                                                                                                                                                                                                                                                                                                                                                                                                                                    final checks8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    added eqs70
                                                                                                                                                                                                                                                                                                                                                                                                                                                    del clause6
                                                                                                                                                                                                                                                                                                                                                                                                                                                    arith eq adapter8
                                                                                                                                                                                                                                                                                                                                                                                                                                                    memory50.700000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    max memory103.390000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    num allocs53861068556.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.014s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                        (y <> [] && List.hd y = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (y = []) && Ordinal.count y >= 0 && Ordinal.count (List.tl y) >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> not
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                               (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                               (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                    • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                      into
                                                                                                                                                                                                                                                                                                                                                                                                                                                      (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                       ((((y <> [] && List.hd y = x) && not (y = [])) && Ordinal.count y >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                        && Ordinal.count (List.tl y) >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                             (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              && not (List.tl y = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                         (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                      []
                                                                                                                                                                                                                                                                                                                                                                                                                                                      rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                        forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                          (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_3229|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                …
                                                                                                                                                                                                                                                                                                                                                                                                                                                          expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                          • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                            (|count_`ty_0 list`_3229| (|get.::.1_3207| y_3217))
                                                                                                                                                                                                                                                                                                                                                                                                                                                            expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                            • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                              (|count_`ty_0 list`_3229| y_3217)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                (let ((a!1 (th-lemma (or (= y_3217 |[]_2|)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (not ((_ is (|[]_2| () |`ty_0 li…

                                                                                                                                                                                                                                                                                                                                                                                                                                                              call `num_occurs x (List.tl y)` from `num_occurs x y`
                                                                                                                                                                                                                                                                                                                                                                                                                                                              originalnum_occurs x y
                                                                                                                                                                                                                                                                                                                                                                                                                                                              subnum_occurs x (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              original ordinalOrdinal.Int (Ordinal.count y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                              sub ordinalOrdinal.Int (Ordinal.count (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                              path[not (y <> [] && List.hd y = x) && not (y = [])]
                                                                                                                                                                                                                                                                                                                                                                                                                                                              proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                              detailed proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                              ground_instances3
                                                                                                                                                                                                                                                                                                                                                                                                                                                              definitions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                              inductions0
                                                                                                                                                                                                                                                                                                                                                                                                                                                              search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                              0.016s
                                                                                                                                                                                                                                                                                                                                                                                                                                                              details
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                              smt_stats
                                                                                                                                                                                                                                                                                                                                                                                                                                                              num checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith assert lower5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith pivots4
                                                                                                                                                                                                                                                                                                                                                                                                                                                              rlimit count2254
                                                                                                                                                                                                                                                                                                                                                                                                                                                              mk clause23
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype occurs check26
                                                                                                                                                                                                                                                                                                                                                                                                                                                              mk bool var62
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith assert upper7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype splits5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              decisions19
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith add rows7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              propagations33
                                                                                                                                                                                                                                                                                                                                                                                                                                                              conflicts9
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith fixed eqs4
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype accessor ax5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith conflicts1
                                                                                                                                                                                                                                                                                                                                                                                                                                                              datatype constructor ax9
                                                                                                                                                                                                                                                                                                                                                                                                                                                              final checks7
                                                                                                                                                                                                                                                                                                                                                                                                                                                              added eqs41
                                                                                                                                                                                                                                                                                                                                                                                                                                                              del clause5
                                                                                                                                                                                                                                                                                                                                                                                                                                                              arith eq adapter3
                                                                                                                                                                                                                                                                                                                                                                                                                                                              memory50.700000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              max memory103.390000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              num allocs53338129789.000000
                                                                                                                                                                                                                                                                                                                                                                                                                                                              Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.016s]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  not (y <> [] && List.hd y = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && not (y = []) && Ordinal.count y >= 0 && Ordinal.count (List.tl y) >= 0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  ==> not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 (((not (y <> [] && List.hd y = x) && not (y = [])) && Ordinal.count y >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  && Ordinal.count (List.tl y) >= 0)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                 || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (((List.tl y) <> [] && List.hd (List.tl y) = x) && not (List.tl y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (not ((List.tl y) <> [] && List.hd (List.tl y) = x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (List.tl y = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                || Ordinal.( << ) (Ordinal.Int (Ordinal.count (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                   (Ordinal.Int (Ordinal.count y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    (|Ordinal.<<_102| (|Ordinal.Int_93| (|count_`ty_0 list`_3229|
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          …
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (|count_`ty_0 list`_3229| (|get.::.1_3207| y_3217))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • unroll
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expr
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (|count_`ty_0 list`_3229| y_3217)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • unsat
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (let ((a!1 (= (|count_`ty_0 list`_3229| y_3217)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (+ 1 (|count_`ty_0 list`_3229| (|get.:…

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                        In [26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        theorem num_occur_merge a x y =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [@@induct functional merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Out[26]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        val num_occur_merge : int -> int list -> int list -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs a (merge x y) = num_occurs a x + num_occurs a y.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        We shall induct according to a scheme derived from merge.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             && not (y = []) && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                ==> φ y x a).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not ((List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        This simplifies, using the definition of merge to the following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 3.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         C0. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         C1. 0 = num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 3.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. y = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         0 = num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 3.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. x = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         0 = num_occurs a x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. List.hd y <= List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a x + num_occurs a (List.tl y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H1. not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H2. not (List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         H3. num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (List.tl x) + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        But simplification reduces this to true, using the definitions of merge and
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                         Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:def merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            (:induct merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        definitions10
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        0.163s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                        • start[0.163s, "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.163s, "1"] num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • induction on (functional merge)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            :scheme (not (List.hd x < List.hd y && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && not (not (List.hd x < List.hd y) && not (y = []) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && not (y = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (List.hd x < List.hd y) && φ (List.tl y) x a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       && (not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           && not (y = []) && List.hd x < List.hd y && φ y (List.tl x) a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           ==> φ y x a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          • Split (((not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not ((List.hd y <= List.hd x && not (y = [])) && not (x = [])))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (((not (x = []) && not (y = [])) && List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs a x + num_occurs a (List.tl y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        || num_occurs a (merge x y) = num_occurs a x + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   && (not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       (((not (x = []) && not (y = [])) && not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a (List.tl x) + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || num_occurs a (merge x y) = num_occurs a x + num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   :cases [((not (List.hd y <= List.hd x) && not (y = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = num_occurs a x + num_occurs a y;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || num_occurs a (merge x y) = num_occurs a x + num_occurs a y])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              (((x = [] || y = []) || List.hd y <= List.hd x) || not (num_occurs a (merge (List.tl x) y) = num_occurs a (List.tl x) + num_occurs a y)) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • start[0.160s, "1"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((x = [] || y = []) || List.hd y <= List.hd x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (num_occurs a (merge (List.tl x) y) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       num_occurs a (List.tl x) + num_occurs a y))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (((x = [] || y = []) || not (List.hd y <= List.hd x)) || not (num_occurs a (merge x (List.tl y)) = num_occurs a x + num_occurs a (List.tl y))) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • start[0.160s, "2"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      (((x = [] || y = []) || not (List.hd y <= List.hd x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       || not
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          (num_occurs a (merge x (List.tl y)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           num_occurs a x + num_occurs a (List.tl y)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    true
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    [num_occurs, num_occurs, merge]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = []) || (List.hd y <= List.hd x && not (y = [])) && not (x = [])) || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • start[0.160s, "3"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          ((not (List.hd y <= List.hd x) && not (y = [])) && not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           || (List.hd y <= List.hd x && not (y = [])) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          || num_occurs a (merge x y) = num_occurs a x + num_occurs a y
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      • simplify
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        into
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ((((not (y = []) || List.hd y <= List.hd x) || 0 = num_occurs a y) || x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         && (((not (y = []) || not (List.hd y <= List.hd x)) || 0 = num_occurs a y)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             || x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && (0 = num_occurs a x || not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        expansions
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        merge
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        rewrite_steps
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          forward_chaining
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            • Subproof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    In [27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    theorem num_occurs_arith (x : int list) (a : int) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      ==>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      num_occurs a x - num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@induct functional num_occurs]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      [@@rewrite]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Out[27]:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    val num_occurs_arith : int list -> int -> bool = <fun>
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Goal:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    x <> [] && List.tl x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ==> num_occurs a (odds (List.tl x)) = num_occurs a x - num_occurs a (odds x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1 nontautological subgoal.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    We shall induct according to a scheme derived from num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Induction scheme:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     (not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      && not (not (x <> [] && List.hd x = a) && not (x = [])) ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     && (not (x = []) && not (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> φ a x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        && (not (x = []) && (x <> [] && List.hd x = a) && φ a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            ==> φ a x).
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    3 nontautological subgoals.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not ((x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (not (x <> [] && List.hd x = a) && not (x = []))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. not (x <> [] && List.hd x = a)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. not (List.tl x = []) && not (List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (List.tl x) + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C2. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (1 + num_occurs a (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 2.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs a (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs a (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. List.hd x = a
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. not (List.tl x = []) && not (List.tl (List.tl x) = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         ==> num_occurs a (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             num_occurs a (List.tl x) + -1 * num_occurs a (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. not (x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H5. not (List.tl x = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs a x + -1 * num_occurs a (odds x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    This simplifies, using the definitions of num_occurs and odds to the
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    following 3 subgoals:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.3:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. num_occurs (List.hd x) (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs (List.hd x) (List.tl (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs (List.hd x) (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C0. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     C1. num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.2:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. num_occurs (List.hd x) (odds (List.tl (List.tl x))) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         (1 + num_occurs (List.hd x) (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         + -1 * num_occurs (List.hd x) (odds (List.tl x))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl (List.tl x)) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H3. List.hd (List.tl x) = List.hd x
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H4. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definition of num_occurs.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Subgoal 1.1:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H0. x <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H1. List.tl (List.tl x) = []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     H2. (List.tl x) <> []
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |---------------------------------------------------------------------------
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs (List.hd x) (odds (List.tl x)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     num_occurs (List.hd x) (List.tl x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     + -1 * num_occurs (List.hd x) (odds (List.tl (List.tl x)))
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    But simplification reduces this to true, using the definitions of num_occurs
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    and odds.
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     Rules:
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:def odds)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        (:induct num_occurs)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Proved
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    proof
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    ground_instances0
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    definitions26
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    inductions1
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    search_time
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    0.525s
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    Expand
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • start[0.525s, "Goal"]
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        not (:var_0: = []) && not (List.tl :var_0: = [])
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        ==> num_occurs :var_1: (odds (List.tl :var_0:)) =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            num_occurs :var_1: :var_0: - num_occurs :var_1: (odds :var_0:)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    • subproof

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                And now, our second main theorem at last:

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

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Merge Sort is Correct!

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      To recap, we've proved:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      theorem merge_sort_sorts x =
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       is_sorted (merge_sort x)
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      and

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

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      Beautiful! Happy proving (and sorting)!