needs "Examples/seq-compiled.hl";;
flyspeck_needs "hypermap/hypermap.hl";;
(* Module Seq2*)
module Seq2 = struct
open Ssrbool;;
open Ssrnat;;
open Seq;;
parse_as_infix ("::", (12, "right"));;
override_interface ("::", `CONS`);;
make_overloadable "++" `:A -> A -> A`;;
overload_interface ("++", `cat`);;
parse_as_infix("<-", (11, "right"));;
override_interface("<-", `MEM`);;
let delete_at = (GEN_ALL o define) `delete_at i [] = [] /\ delete_at 0 (h :: t) = t /\
delete_at (SUC i) (h :: t) = h :: delete_at i t`;;
let delete1 = (GEN_ALL o define)
`delete1 x [] = [] /\ delete1 x (h :: t) = if x = h then t else h :: delete1 x t`;;
let butlast = (GEN_ALL o define)
`butlast [] = [] /\ butlast [h] = [] /\ butlast (h :: (h2 :: t)) = h :: butlast (h2 :: t)`;;
let next_el = new_definition `next_el s x =
if (indexl x s = sizel s - 1) then (headl x s) else (nth x s (indexl x s + 1))`;;
let prev_el = new_definition `prev_el s x =
if ~(MEM x s) then x
else if (indexl x s = 0) then (last x s) else (nth x s (indexl x s - 1))`;;
let EL = GEN_ALL EL;;
let HD = GEN_ALL HD;;
let TL = GEN_ALL TL;;
let MEM = GEN_ALL MEM;;
let ALL = GEN_ALL ALL;;
let ALL2 = GEN_ALL ALL2;;
let uniq = GEN_ALL uniq;;
let foldr = GEN_ALL foldr;;
let iter = GEN_ALL iter;;
let undup = GEN_ALL undup;;
let iota = GEN_ALL iota;;
let map = GEN_ALL map;;
let zip = GEN_ALL zip;;
let take = GEN_ALL Seq.take;;
(* Lemma pair_expand *)
let pair_expand = Sections.section_proof ["p"]
`p = FST p, SND p`
[
((ALL_TAC) THEN (done_tac));
];;
(* Section SeqList *)
Sections.begin_section "SeqList";;
(* Lemma ALL_all *)
let ALL_all = Sections.section_proof []
`ALL = all`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] []))))) THEN (move ["P"])) THEN ((THENL) elim [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("ALL", [ALL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("all", [all]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma APPEND_cat *)
let APPEND_cat = Sections.section_proof []
`APPEND = cat`
[
((repeat_tactic 1 9 (((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] []))))) THEN ((THENL) elim [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("APPEND", [APPEND]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma head_HD *)
let head_HD = Sections.section_proof ["x0";"s"]
`0 < sizel s ==> headl x0 s = HD s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("head", [head]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac ->(use_arg_then2 ("ltn0", [ltn0]))(fun tmp_arg1 -> (use_arg_then2 ("HD", [HD]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma EL_nth *)
let EL_nth = Sections.section_proof ["x0";"s";"i"]
`i < sizel s ==> EL i s = nth x0 s i`
[
((((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IH"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h"]) THEN (move ["t"]))])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("EL", [EL]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] [])))))) THEN (TRY ((arith_tac))));
((((((use_arg_then2 ("TL", [TL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["n_lt"])) THEN (((use_arg_then2 ("IH", [])) (disch_tac [])) THEN (clear_assumption "IH") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma EL_map *)
let EL_map = Sections.section_proof ["i";"s";"f"]
`i < LENGTH s ==> EL i (map f s) = f (EL i s)`
[
((((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (BETA_TAC THEN (move ["i_lt"])) THEN ((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("nth_map", [nth_map])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (term_tac exists_tac)) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
((((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma EL_mkseq *)
let EL_mkseq = Sections.section_proof ["i";"f";"n"]
`i < n ==> EL i (mkseq f n) = f i`
[
((BETA_TAC THEN (move ["i_lt"])) THEN ((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_EL_P *)
let all_EL_P = Sections.section_proof ["a";"s"]
`(!i. i < sizel s ==> a (EL i s)) <=> all a s`
[
((THENL) (split_tac) [(move ["h"]); ((move ["all_s"]) THEN (move ["i"]) THEN (move ["i_lt"]))]);
((((fun arg_tac -> (use_arg_then2 ("all_nthP", [all_nthP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (move ["i"]) THEN (move ["i_lt"]));
(((((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("h", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((in_tac ["all_s"] false (((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((((use_arg_then2 ("all_s", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM_EL", [MEM_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma EL_take *)
let EL_take = Sections.section_proof ["n";"i";"s"]
`i < n /\ i < sizel s ==> EL i (take n s) = EL i s`
[
(BETA_TAC THEN (case THEN ((move ["i_lt_n"]) THEN (move ["i_lt"]))));
((THENL_FIRST) ((repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))))) ((((use_arg_then2 ("i_lt_n", [])) (disch_tac [])) THEN (clear_assumption "i_lt_n") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((use_arg_then2 ("nth_take", [nth_take]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma EL_index *)
let EL_index = Sections.section_proof ["x";"s"]
`x <- s ==> EL (indexl x s) s = x`
[
((BETA_TAC THEN (move ["mem_x"])) THEN ((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma ALL2_cat *)
let ALL2_cat = Sections.section_proof ["f";"s1";"t1";"s2";"t2"]
`sizel s1 = sizel s2 ==>
(ALL2 f (s1 ++ t1) (s2 ++ t2) <=> ALL2 f s1 s2 /\ ALL2 f t1 t2)`
[
((((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h1"]) THEN (move ["r1"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["r2"]))])) THEN ((repeat_tactic 1 9 (((fun arg_tac ->(use_arg_then2 ("size_cons", [size_cons]))(fun tmp_arg1 -> (use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ALL2", [ALL2]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (TRY ((arith_tac))));
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("Ih", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("andbA", [andbA]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section SeqList *)
let ALL_all = Sections.finalize_theorem ALL_all;;
let APPEND_cat = Sections.finalize_theorem APPEND_cat;;
let head_HD = Sections.finalize_theorem head_HD;;
let EL_nth = Sections.finalize_theorem EL_nth;;
let EL_map = Sections.finalize_theorem EL_map;;
let EL_mkseq = Sections.finalize_theorem EL_mkseq;;
let all_EL_P = Sections.finalize_theorem all_EL_P;;
let EL_take = Sections.finalize_theorem EL_take;;
let EL_index = Sections.finalize_theorem EL_index;;
let ALL2_cat = Sections.finalize_theorem ALL2_cat;;
Sections.end_section "SeqList";;
(* Section Misc *)
Sections.begin_section "Misc";;
(* Lemma length_le_1 *)
let length_le_1 = Sections.section_proof ["s"]
`LENGTH s <= 1 ==> s = [] \/ s = [HD s]`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma count0 *)
let count0 = Sections.section_proof ["P";"s"]
`count P s = 0 <=> all (predC P) s`
[
(((((use_arg_then2 ("all_predC", [all_predC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma count_filterI *)
let count_filterI = Sections.section_proof ["a1";"a2";"s"]
`count a1 (filter a2 s) = count (predI a1 a2) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("predI", [predI]))(thm_tac (new_rewrite [1] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("IH", []))(gsym_then (thm_tac (new_rewrite [] [])))))));
((((fun arg_tac -> arg_tac (Arg_term (`a2 h`))) (disch_tac [])) THEN case THEN (simp_tac)) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma seq_eq_mkseq *)
let seq_eq_mkseq = Sections.section_proof ["x0";"s"]
`s = mkseq (nth x0 s) (sizel s)`
[
(((fun arg_tac -> (use_arg_then2 ("eq_from_nth", [eq_from_nth])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac apply_tac)) THEN (((((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["i_lt"])) THEN (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma seq_wf_ind *)
let seq_wf_ind = Sections.section_proof ["P"]
`(!s:(A)list. (!l. LENGTH l < LENGTH s ==> P l) ==> P s) ==> (!s. P s)`
[
(((fun arg_tac -> (use_arg_then2 ("WF_MEASURE", [WF_MEASURE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`LENGTH:(A)list->num`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC);
((((((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL WF_IND)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEASURE", [MEASURE]))(thm_tac (new_rewrite [] []))))) THEN ((fun arg_tac -> (conv_thm_tac DISCH_THEN) (fun fst_arg -> (use_arg_then2 ("P", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac MP_TAC)) THEN (move ["h"]) THEN (move ["h2"]) THEN (move ["s"])) THEN (((use_arg_then2 ("h", [])) (disch_tac [])) THEN (clear_assumption "h") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma length_eq_imp_length_tl_eq *)
let length_eq_imp_length_tl_eq = Sections.section_proof ["s1";"s2"]
`LENGTH (s1:(A)list) = LENGTH (s2:(A)list) ==>
LENGTH (TL s1) = LENGTH (TL s2)`
[
((((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN (move ["s2"])) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] [])))));
((((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH_EQ_NIL", [LENGTH_EQ_NIL]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((BETA_TAC THEN (move ["len_eq"])) THEN ((((use_arg_then2 ("TL", [TL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH_TL", [LENGTH_TL]))(thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("len_eq", [])) (disch_tac [])) THEN (clear_assumption "len_eq") THEN ((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] [])))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("len_eq", [])) (disch_tac [])) THEN (clear_assumption "len_eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma ge_length_imp_EL_eq *)
let ge_length_imp_EL_eq = Sections.section_proof ["k";"s1";"s2"]
`LENGTH s1 = LENGTH s2 /\ LENGTH s1 <= k ==> EL k s1 = EL k s2`
[
((((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN ((use_arg_then2 ("k", [])) (disch_tac [])) THEN (clear_assumption "k") THEN elim) [ALL_TAC; ((move ["k"]) THEN (move ["IH"]))]) THEN (move ["s1"]) THEN (move ["s2"])) THEN (repeat_tactic 1 9 (((use_arg_then2 ("EL", [EL]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("leqn0", [leqn0]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN ((move ["len_eq"]) THEN (move ["s1_0"])))) THEN (((use_arg_then2 ("s1_0", [])) (disch_tac [])) THEN ((use_arg_then2 ("len_eq", [])) (disch_tac [])) THEN (clear_assumption "len_eq") THEN BETA_TAC));
((((((use_arg_then2 ("s1_0", []))(thm_tac (new_rewrite [1] [])))) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("LENGTH_EQ_NIL", [LENGTH_EQ_NIL]))(thm_tac (new_rewrite [] [])))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(BETA_TAC THEN (case THEN ((move ["len_eq"]) THEN (move ["len_le"]))));
(((fun arg_tac -> arg_tac (Arg_term (`LENGTH s2 = 0`))) (disch_eq_tac "s2_len" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((((use_arg_then2 ("s2_len", [])) (disch_tac [])) THEN ((use_arg_then2 ("len_eq", [])) (disch_tac [])) THEN (clear_assumption "len_eq") THEN BETA_TAC) THEN (((((use_arg_then2 ("s2_len", []))(thm_tac (new_rewrite [1] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("LENGTH_EQ_NIL", [LENGTH_EQ_NIL]))(thm_tac (new_rewrite [] [])))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("IH", [])) (disch_tac [])) THEN (clear_assumption "IH") THEN (DISCH_THEN apply_tac)) THEN ((((fun arg_tac -> (use_arg_then2 ("length_eq_imp_length_tl_eq", [length_eq_imp_length_tl_eq])) (fun fst_arg -> (use_arg_then2 ("len_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)));
((THENL_FIRST) (((use_arg_then2 ("LENGTH_TL", [LENGTH_TL]))(thm_tac (new_rewrite [] [])))) ((((use_arg_then2 ("s2_len", [])) (disch_tac [])) THEN (clear_assumption "s2_len") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("len_eq", [])) (disch_tac [])) THEN (clear_assumption "len_eq") THEN ((use_arg_then2 ("len_le", [])) (disch_tac [])) THEN (clear_assumption "len_le") THEN ((use_arg_then2 ("s2_len", [])) (disch_tac [])) THEN (clear_assumption "s2_len") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma mem_nseq *)
let mem_nseq = Sections.section_proof ["n";"x";"y"]
`y <- nseq n x <=> 0 < n /\ y = x`
[
(((((use_arg_then2 ("MEM_EXISTS_EL", [MEM_EXISTS_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_nseq", [size_nseq]))(thm_tac (new_rewrite [] []))))) THEN ((THENL) (split_tac) [((case THEN (move ["i"])) THEN (case THEN (move ["i_lt"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))); ((case THEN (move ["n_gt0"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))]));
(((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nseq", [size_nseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_nseq", [nth_nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_lt", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
(((fun arg_tac -> arg_tac (Arg_term (`0`))) (term_tac exists_tac)) THEN ((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nseq", [size_nseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_nseq", [nth_nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_gt0", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_flatten *)
let mem_flatten = Sections.section_proof ["x";"L"]
`MEM x (flatten L) <=> ?l. MEM l L /\ MEM x l`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("L", [])) (disch_tac [])) THEN (clear_assumption "L") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) (((((use_arg_then2 ("flatten0", [flatten0]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac)));
((((use_arg_then2 ("flatten_cons", [flatten_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))));
(((THENL) ((THENL) (split_tac) [((THENL) case [(move ["xh"]); ((case THEN (move ["l"])) THEN (move ["h"]))]); ((case THEN (move ["l"])) THEN (case THEN ((move ["h1"]) THEN (move ["xl"]))))]) [((use_arg_then2 ("h", [])) (term_tac exists_tac)); ((use_arg_then2 ("l", [])) (term_tac exists_tac)); (ALL_TAC)]) THEN (BETA_TAC THEN ((TRY done_tac))));
(((THENL) (((use_arg_then2 ("h1", [])) (disch_tac [])) THEN (clear_assumption "h1") THEN case) [((((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))); (move ["lt"])]) THEN (DISJ2_TAC) THEN ((use_arg_then2 ("l", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma size1 *)
let size1 = Sections.section_proof ["x"]
`sizel [x] = 1`
[
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size1_eq *)
let size1_eq = Sections.section_proof ["s"]
`sizel s = 1 <=> ?x. s = [x]`
[
((THENL_LAST) ((THENL) (split_tac) [ALL_TAC; ((case THEN (move ["x"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))]) ((((use_arg_then2 ("size1", [size1]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) ((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (arith_tac) THEN (done_tac)));
((((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_eq0", [size_eq0]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((use_arg_then2 ("h", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma cons_head_drop1 *)
let cons_head_drop1 = Sections.section_proof ["x0";"s"]
`0 < sizel s ==> s = (headl x0 s) :: (dropl 1 s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((repeat_tactic 0 10 (((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("ltn0", [ltn0]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma last_eq *)
let last_eq = Sections.section_proof ["a";"b";"s"]
`0 < sizel s ==> last a s = last b s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma last_drop *)
let last_drop = Sections.section_proof ["x0";"s";"n"]
`n < sizel s ==> last x0 (dropl n s) = last x0 s`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]) THEN ((THENL) case [ALL_TAC; (move ["n"])]))]) THEN (((((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("size_cons", [size_cons]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["n_lt"])));
(((((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("last_eq", [last_eq])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("h", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Finalization of the section Misc *)
let length_le_1 = Sections.finalize_theorem length_le_1;;
let count0 = Sections.finalize_theorem count0;;
let count_filterI = Sections.finalize_theorem count_filterI;;
let seq_eq_mkseq = Sections.finalize_theorem seq_eq_mkseq;;
let seq_wf_ind = Sections.finalize_theorem seq_wf_ind;;
let length_eq_imp_length_tl_eq = Sections.finalize_theorem length_eq_imp_length_tl_eq;;
let ge_length_imp_EL_eq = Sections.finalize_theorem ge_length_imp_EL_eq;;
let mem_nseq = Sections.finalize_theorem mem_nseq;;
let mem_flatten = Sections.finalize_theorem mem_flatten;;
let size1 = Sections.finalize_theorem size1;;
let size1_eq = Sections.finalize_theorem size1_eq;;
let cons_head_drop1 = Sections.finalize_theorem cons_head_drop1;;
let last_eq = Sections.finalize_theorem last_eq;;
let last_drop = Sections.finalize_theorem last_drop;;
Sections.end_section "Misc";;
(* Section MoreZip *)
Sections.begin_section "MoreZip";;
(* Lemma mem_zip *)
let mem_zip = Sections.section_proof ["s1";"s2";"a";"b"]
`MEM (a,b) (zip s1 s2) ==> MEM a s1 /\ MEM b s2`
[
((((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t2"]))])) THEN ((((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("PAIR_EQ", [PAIR_EQ]))(thm_tac (new_rewrite [] []))))));
(((THENL) case [(case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))); (DISCH_THEN (fun snd_th -> (use_arg_then2 ("Ih", [])) (thm_tac (match_mp_then snd_th MP_TAC))))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma EL_zip *)
let EL_zip = Sections.section_proof ["s1";"s2";"i"]
`sizel s1 = sizel s2 /\ i < sizel s1
==> EL i (zip s1 s2) = (EL i s1, EL i s2)`
[
(BETA_TAC THEN (case THEN ((move ["size_eq"]) THEN (move ["i_lt"]))));
((fun arg_tac -> arg_tac (Arg_term (`HD s1`))) (term_tac (set_tac "x0")));
((fun arg_tac -> arg_tac (Arg_term (`HD s2`))) (term_tac (set_tac "y0")));
((THENL_FIRST) (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x0,y0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`zip s1 s2`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) (((((use_arg_then2 ("size1_zip", [size1_zip]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("i_lt", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("nth_zip", [nth_zip]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("PAIR_EQ", [PAIR_EQ]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma take_zip *)
let take_zip = Sections.section_proof ["s1";"s2";"n"]
`take n (zip s1 s2) = zip (take n s1) (take n s2)`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h1"]) THEN (move ["t1"]) THEN (move ["Ih1"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t2"]))])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((THENL) case [ALL_TAC; (move ["n"])]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma drop_zip *)
let drop_zip = Sections.section_proof ["s1";"s2";"n"]
`dropl n (zip s1 s2) = zip (dropl n s1) (dropl n s2)`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h1"]) THEN (move ["t2"]) THEN (move ["Ih1"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t2"]))])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((THENL) case [ALL_TAC; (move ["n"])]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("zip", [zip]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rot_zip *)
let rot_zip = Sections.section_proof ["s1";"s2";"n"]
`sizel s1 = sizel s2
==> rot n (zip s1 s2) = zip (rot n s1) (rot n s2)`
[
(BETA_TAC THEN (move ["size_eq"]));
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop_zip", [drop_zip]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take_zip", [take_zip]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("zip_cat", [zip_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("rot", [rot]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr_zip *)
let rotr_zip = Sections.section_proof ["s1";"s2";"n"]
`sizel s1 = sizel s2
==> rotr n (zip s1 s2) = zip (rotr n s1) (rotr n s2)`
[
(BETA_TAC THEN (move ["size_eq"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size1_zip", [size1_zip]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("rot_zip", [rot_zip]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section MoreZip *)
let mem_zip = Sections.finalize_theorem mem_zip;;
let EL_zip = Sections.finalize_theorem EL_zip;;
let take_zip = Sections.finalize_theorem take_zip;;
let drop_zip = Sections.finalize_theorem drop_zip;;
let rot_zip = Sections.finalize_theorem rot_zip;;
let rotr_zip = Sections.finalize_theorem rotr_zip;;
Sections.end_section "MoreZip";;
(* Section MoreUniq *)
Sections.begin_section "MoreUniq";;
(* Lemma uniq_small_size *)
let uniq_small_size = Sections.section_proof ["l"]
`sizel l < 2 ==> uniq l`
[
(((THENL) (((use_arg_then2 ("l", [])) (disch_tac [])) THEN (clear_assumption "l") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((((use_arg_then2 ("uniq", [uniq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
(((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN case) [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("uniq", [uniq]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma mem_imp_not_uniq_cat *)
let mem_imp_not_uniq_cat = Sections.section_proof ["x";"l1";"l2"]
`MEM x l1 /\ MEM x l2 ==> ~(uniq (cat l1 l2))`
[
((BETA_TAC THEN (case THEN ((move ["x_l1"]) THEN (move ["x_l2"])))) THEN ((((use_arg_then2 ("cat_uniq", [cat_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("negbK", [negbK]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)));
((DISJ2_TAC) THEN (DISJ1_TAC) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma uniq_nthP *)
let uniq_nthP = Sections.section_proof ["x0";"s"]
`uniq s <=> (!i j. i < j /\ j < sizel s ==> ~(nth x0 s i = nth x0 s j))`
[
((THENL_FIRST) (((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("uniq", [uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))))) ((arith_tac) THEN (done_tac)));
((THENL) (split_tac) [((case THEN ((move ["n_mem"]) THEN (move ["uniq_t"]))) THEN (move ["i"]) THEN (move ["j"]) THEN (case THEN ((move ["i_lt_j"]) THEN (move ["j_lt"])))); (move ["h"])]);
((((THENL) (((use_arg_then2 ("j_lt", [])) (disch_tac [])) THEN (clear_assumption "j_lt") THEN ((use_arg_then2 ("i_lt_j", [])) (disch_tac [])) THEN (clear_assumption "i_lt_j") THEN ((use_arg_then2 ("j", [])) (disch_tac [])) THEN (clear_assumption "j") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN case) [ALL_TAC; (move ["i"])]) THEN ((THENL) case [ALL_TAC; (move ["j"])])) THEN (TRY ((arith_tac))));
(((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (move ["_"]) THEN (move ["j_lt"]));
((((use_arg_then2 ("n_mem", [])) (disch_tac [])) THEN (clear_assumption "n_mem") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
(((repeat_tactic 1 9 (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (move ["i_lt_j"]) THEN (move ["j_lt"]));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("iffLR", [iffLR])) (fun fst_arg -> (use_arg_then2 ("IH", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("uniq_t", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
(split_tac);
((((use_arg_then2 ("h", [])) (disch_tac [])) THEN (clear_assumption "h") THEN ((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac) THEN (move ["mem_h"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("NOT_FORALL_THM", [NOT_FORALL_THM]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("NOT_IMP", [NOT_IMP]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negbK", [negbK]))(thm_tac (new_rewrite [] []))))));
(((fun arg_tac -> arg_tac (Arg_term (`0`))) (term_tac exists_tac)) THEN ((fun arg_tac -> arg_tac (Arg_term (`SUC (indexl h t)`))) (term_tac exists_tac)));
(((((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (move ["i"]) THEN (move ["j"]) THEN (case THEN ((move ["i_lt_j"]) THEN (move ["j_lt"]))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("h", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`SUC i`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`SUC j`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("j_lt", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_lt_j", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma uniq_map_nth *)
let uniq_map_nth = Sections.section_proof ["x0";"p";"s"]
`uniq s /\ uniq p /\ all (\i:num. i < sizel s) p
==> uniq (map (nth x0 s) p)`
[
(((((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN ALL_TAC THEN (case THEN (move ["uniq_s"])) THEN (case THEN (move ["uniq_p"])) THEN (move ["in_p"]));
(((((use_arg_then2 ("map_inj_in_uniq", [map_inj_in_uniq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (move ["i"]) THEN (move ["j"]) THEN (case THEN ALL_TAC) THEN (case THEN ((move ["i_p"]) THEN (move ["j_p"]))));
(((((fun arg_tac -> (use_arg_then2 ("nth_uniq", [nth_uniq])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_p", []))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma uniq_index_inj *)
let uniq_index_inj = Sections.section_proof ["x";"y";"s"]
`uniq s /\ x <- s /\ y <- s ==> (indexl x s = indexl y s <=> x = y)`
[
((BETA_TAC THEN (case THEN (move ["uniq_s"])) THEN (case THEN (move ["xs"])) THEN (move ["ys"])) THEN ((THENL) (split_tac) [ALL_TAC; ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))]));
((((use_arg_then2 ("ys", [])) (disch_tac [])) THEN (clear_assumption "ys") THEN ((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN BETA_TAC) THEN (((repeat_tactic 1 9 (((use_arg_then2 ("MEM_EXISTS_EL", [MEM_EXISTS_EL]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ALL_TAC THEN (case THEN (move ["i"])) THEN (case THEN (move ["i_lt"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (case THEN (move ["j"])) THEN (case THEN (move ["j_lt"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))));
((((repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section MoreUniq *)
let uniq_small_size = Sections.finalize_theorem uniq_small_size;;
let mem_imp_not_uniq_cat = Sections.finalize_theorem mem_imp_not_uniq_cat;;
let uniq_nthP = Sections.finalize_theorem uniq_nthP;;
let uniq_map_nth = Sections.finalize_theorem uniq_map_nth;;
let uniq_index_inj = Sections.finalize_theorem uniq_index_inj;;
Sections.end_section "MoreUniq";;
(* Section MoreIndex *)
Sections.begin_section "MoreIndex";;
(* Lemma index_nil *)
let index_nil = Sections.section_proof ["x"]
`indexl x [] = 0`
[
(((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("find", [find]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_cons *)
let index_cons = Sections.section_proof ["x";"h";"t"]
`indexl x (h :: t) = if x = h then 0 else SUC (indexl x t)`
[
(((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [1] [])))) THEN (((use_arg_then2 ("find", [find]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("pred1", [pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index", [index]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN (done_tac));
];;
(* Lemma index_eq_size *)
let index_eq_size = Sections.section_proof ["x";"s"]
`~(MEM x s) <=> indexl x s = sizel s`
[
(((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_find", [has_find]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn_neqAle", [ltn_neqAle]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("find_size", [find_size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negbK", [negbK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_head *)
let index_head = Sections.section_proof ["x0";"s"]
`indexl (headl x0 s) s = 0`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("find", [find]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_take *)
let index_take = Sections.section_proof ["s";"n";"x"]
`indexl x (take n s) = if indexl x s < n then (indexl x s) else n`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; (move ["n"])])) THEN ((((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_nil", [index_nil]))(thm_tac (new_rewrite [] [])))))) THEN (TRY ((arith_tac))));
(repeat_tactic 1 9 (((use_arg_then2 ("index_cons", [index_cons]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "x_eq_h" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> arg_tac (Arg_term (`_1 < n:num`))) (disch_tac [])) THEN case) THEN (done_tac));
];;
(* Lemma index_drop_le *)
let index_drop_le = Sections.section_proof ["s";"n";"x"]
`n <= indexl x s ==> indexl x (dropl n s) = indexl x s - n`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; (move ["n"])])) THEN ((((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_nil", [index_nil]))(thm_tac (new_rewrite [] [])))))) THEN (TRY ((arith_tac))));
(repeat_tactic 1 9 (((use_arg_then2 ("index_cons", [index_cons]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "x_eq_h" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((arith_tac) THEN (done_tac)));
((((((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("Ih", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_drop_uniq *)
let index_drop_uniq = Sections.section_proof ["s";"n";"x"]
`uniq s ==>
indexl x (dropl n s) = if n <= indexl x s then (indexl x s - n) else (sizel s - n)`
[
(BETA_TAC THEN (move ["uniq_s"]));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`n < sizel s`))) (disch_eq_tac "n_lt" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
((((use_arg_then2 ("drop_oversize", [drop_oversize]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqNgt", [leqNgt]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("index_nil", [index_nil]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN ((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("index_size", [index_size])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`n:num <= _`))) (disch_eq_tac "n_le" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((((use_arg_then2 ("index_drop_le", [index_drop_le]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("size_drop", [size_drop]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_eq_size", [index_eq_size]))(gsym_then (thm_tac (new_rewrite [] []))))));
(((use_arg_then2 ("uniq_s", [])) (disch_tac [])) THEN (clear_assumption "uniq_s") THEN ((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac) THEN (move ["mem_drop"]));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("mem_imp_not_uniq_cat", [mem_imp_not_uniq_cat])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mem_drop", [mem_drop]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_take", [index_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))));
((in_tac ["n_le"] false (((use_arg_then2 ("NOT_LE", [NOT_LE]))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("n_le", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("n_lt", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section MoreIndex *)
let index_nil = Sections.finalize_theorem index_nil;;
let index_cons = Sections.finalize_theorem index_cons;;
let index_eq_size = Sections.finalize_theorem index_eq_size;;
let index_head = Sections.finalize_theorem index_head;;
let index_take = Sections.finalize_theorem index_take;;
let index_drop_le = Sections.finalize_theorem index_drop_le;;
let index_drop_uniq = Sections.finalize_theorem index_drop_uniq;;
Sections.end_section "MoreIndex";;
(* Section MorePermEq *)
Sections.begin_section "MorePermEq";;
(* Lemma perm_eq_cat *)
let perm_eq_cat = Sections.section_proof ["s1";"t1";"s2";"t2"]
`perm_eq s1 s2 /\ perm_eq t1 t2 ==> perm_eq (s1 ++ t1) (s2 ++ t2)`
[
((((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] [])))))) THEN ALL_TAC THEN (case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) THEN (done_tac));
];;
(* Lemma perm_eq0r *)
let perm_eq0r = Sections.section_proof ["s"]
`perm_eq s [] <=> s = []`
[
(((THENL) (split_tac) [(DISCH_THEN (fun snd_th -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (thm_tac (match_mp_then snd_th MP_TAC)))); (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_eq0", [size_eq0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq0l *)
let perm_eq0l = Sections.section_proof ["s"]
`perm_eq [] s <=> s = []`
[
(((((use_arg_then2 ("perm_eq_sym", [perm_eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq0r", [perm_eq0r]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_pred1P *)
let perm_eq_pred1P = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 <=> (!x. count (pred1 x) s1 = count (pred1 x) s2)`
[
((THENL_FIRST) ((THENL) (split_tac) [ALL_TAC; (move ["count_eq"])]) (((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac)));
((((((use_arg_then2 ("perm_eq", [perm_eq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("same_count1", [same_count1]))(thm_tac (new_rewrite [] []))))) THEN (move ["x"]) THEN (move ["_"])) THEN (done_tac));
];;
(* Lemma perm_eq_filter *)
let perm_eq_filter = Sections.section_proof ["a";"s1";"s2"]
`perm_eq s1 s2 ==> perm_eq (filter a s1) (filter a s2)`
[
((((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count_filterI", [count_filterI]))(thm_tac (new_rewrite [] [])))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_undup *)
let perm_eq_undup = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> perm_eq (undup s1) (undup s2)`
[
((DISCH_THEN (fun snd_th -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (move ["h_mem"]));
((((use_arg_then2 ("perm_eq_pred1P", [perm_eq_pred1P]))(thm_tac (new_rewrite [] [])))) THEN (move ["x"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("count_uniq_mem", [count_uniq_mem]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("undup_uniq", [undup_uniq]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("h_mem", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_map *)
let perm_eq_map = Sections.section_proof ["f";"s1";"s2"]
`perm_eq s1 s2 ==> perm_eq (map f s1) (map f s2)`
[
((((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count_map", [count_map]))(thm_tac (new_rewrite [] [])))))) THEN (move ["eq"]) THEN (move ["P"])) THEN (done_tac));
];;
(* Lemma uniq_perm_eq_alt *)
let uniq_perm_eq_alt = Sections.section_proof ["s1";"s2"]
`uniq s1 /\ sizel s1 = sizel s2 /\ (!x. x <- s1 <=> x <- s2)
==> perm_eq s1 s2`
[
(BETA_TAC THEN (case THEN (move ["uniq1"])) THEN (case THEN (move ["size_eq"])) THEN (move ["mem"]));
(((use_arg_then2 ("uniq_perm_eq", [uniq_perm_eq])) (thm_tac apply_tac)) THEN (repeat_tactic 1 9 (((split_tac) THEN ((TRY done_tac))))));
((((fun arg_tac -> (use_arg_then2 ("perm_uniq", [perm_uniq])) (fun fst_arg -> (use_arg_then2 ("mem", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_perm_eq *)
let all_perm_eq = Sections.section_proof ["a";"s1";"s2"]
`perm_eq s1 s2 ==> (all a s1 <=> all a s2)`
[
((BETA_TAC THEN (move ["perm"])) THEN (((use_arg_then2 ("perm", [])) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["eq"])));
(((repeat_tactic 1 9 (((use_arg_then2 ("all_count", [all_count]))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section MorePermEq *)
let perm_eq_cat = Sections.finalize_theorem perm_eq_cat;;
let perm_eq0r = Sections.finalize_theorem perm_eq0r;;
let perm_eq0l = Sections.finalize_theorem perm_eq0l;;
let perm_eq_pred1P = Sections.finalize_theorem perm_eq_pred1P;;
let perm_eq_filter = Sections.finalize_theorem perm_eq_filter;;
let perm_eq_undup = Sections.finalize_theorem perm_eq_undup;;
let perm_eq_map = Sections.finalize_theorem perm_eq_map;;
let uniq_perm_eq_alt = Sections.finalize_theorem uniq_perm_eq_alt;;
let all_perm_eq = Sections.finalize_theorem all_perm_eq;;
Sections.end_section "MorePermEq";;
(* Section MoreSubseq *)
Sections.begin_section "MoreSubseq";;
(* Lemma all_subseq *)
let all_subseq = Sections.section_proof ["s1";"s2";"P"]
`subseq s1 s2 /\ all P s2 ==> all P s1`
[
(((((use_arg_then2 ("all_filterP", [all_filterP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ((move ["sub"]) THEN (move ["eq"])))) THEN (((use_arg_then2 ("sub", [])) (disch_tac [])) THEN (clear_assumption "sub") THEN BETA_TAC));
((((((use_arg_then2 ("eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subseq_filter", [subseq_filter]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma subseq_tl *)
let subseq_tl = Sections.section_proof ["h";"t";"s"]
`subseq (h :: t) s ==> subseq t s`
[
((BETA_TAC THEN (move ["h"])) THEN ((use_arg_then2 ("subseq_trans", [subseq_trans])) (thm_tac apply_tac)) THEN ((fun arg_tac -> arg_tac (Arg_term (`h :: t`))) (term_tac exists_tac)) THEN (((use_arg_then2 ("subseq_cons", [subseq_cons]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section MoreSubseq *)
let all_subseq = Sections.finalize_theorem all_subseq;;
let subseq_tl = Sections.finalize_theorem subseq_tl;;
Sections.end_section "MoreSubseq";;
(* Section Delete *)
Sections.begin_section "Delete";;
(Sections.add_section_type (mk_var ("x", (`:A`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("s1", (`:(A)list`))); Sections.add_section_type (mk_var ("s2", (`:(A)list`))));;
(Sections.add_section_var (mk_var ("x0", (`:A`))));;
(* Lemma delete1_eq_at *)
let delete1_eq_at = Sections.section_proof ["x";"s"]
`delete1 x s = delete_at (indexl x s) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("index_cons", [index_cons]))(thm_tac (new_rewrite [] []))))));
((((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN ((((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma delete1_hd *)
let delete1_hd = Sections.section_proof ["h";"t"]
`delete1 h (h :: t) = t`
[
((((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma count_delete_at *)
let count_delete_at = Sections.section_proof ["i";"s";"P"]
`i < sizel s ==>
count P (delete_at i s) = count P s - if P (nth x0 s i) then 1 else 0`
[
((((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((THENL) case [ALL_TAC; (move ["i"])])) THEN ((((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (TRY ((arith_tac))));
(((((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["i_lt"]));
((((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`if P h then 1 else 0`))) (term_tac (set_tac "n")));
((fun arg_tac -> arg_tac (Arg_term (`if _1 then _2 else _3`))) (term_tac (set_tac "k")));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`count P t = 0`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k = 0 \/ k = 1`))) (term_tac (have_gen_tac []ALL_TAC))) ((((use_arg_then2 ("k_def", [])) (disch_tac [])) THEN (clear_assumption "k_def") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`k = 0`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))))) ((repeat_tactic 1 9 (((use_arg_then2 ("subn0", [subn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`~P (nth x0 t i)`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))))) ((ALL_TAC) THEN (done_tac))));
((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN ((((use_arg_then2 ("count0", [count0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("all_predC", [all_predC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("hasPn", [hasPn]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN apply_tac) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma count_delete1 *)
let count_delete1 = Sections.section_proof ["x";"s";"P"]
`x <- s ==> count P (delete1 x s) = count P s - if P x then 1 else 0`
[
((BETA_TAC THEN (move ["mem_x"])) THEN ((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_delete_at", [count_delete_at]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma delete_at_eq *)
let delete_at_eq = Sections.section_proof ["i";"s"]
`delete_at i s = s <=> sizel s <= i`
[
((THENL_ROT (-1)) ((((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((THENL) case [ALL_TAC; (move ["i"])])) THEN ((((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] []))))) THEN (TRY ((arith_tac)))));
(((((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `!n. ~(SUC n <= 0)`)))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
(((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `(!n. n = n:num)`))) (disch_tac [])) THEN BETA_TAC THEN ((fun arg_tac -> (conv_thm_tac DISCH_THEN) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel t`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac MP_TAC)));
((((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [1] []))))) THEN ((((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma delete_at_eq_imp *)
let delete_at_eq_imp = Sections.section_proof ["i";"s"]
`~(i < sizel s) ==> delete_at i s = s`
[
(((((use_arg_then2 ("leqNgt", [leqNgt]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("delete_at_eq", [delete_at_eq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma not_mem_delete1 *)
let not_mem_delete1 = Sections.section_proof ["x";"s"]
`~(x <- s) ==> delete1 x s = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN (((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("negb_or", [negb_or]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IH", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) THEN (done_tac));
];;
(* Lemma size_delete_at *)
let size_delete_at = Sections.section_proof ["i";"s"]
`sizel (delete_at i s) = sizel s - if i < sizel s then 1 else 0`
[
((THENL_LAST) (((fun arg_tac -> arg_tac (Arg_term (`i < sizel s`))) (disch_eq_tac "lt" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("delete_at_eq_imp", [delete_at_eq_imp]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("subn0", [subn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((repeat_tactic 1 9 (((use_arg_then2 ("count_predT", [count_predT]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("count_delete_at", [count_delete_at]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("predT", [predT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_delete1 *)
let size_delete1 = Sections.section_proof ["x";"s"]
`sizel (delete1 x s) = sizel s - if x <- s then 1 else 0`
[
(((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_delete_at", [size_delete_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma subseq_delete_at *)
let subseq_delete_at = Sections.section_proof ["i";"s"]
`subseq (delete_at i s) s`
[
((((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((THENL) case [ALL_TAC; (move ["i"])])) THEN ((((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("subseq0", [subseq0]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("subseq_cons", [subseq_cons]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("cat1s", [cat1s]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat1s", [cat1s])) (fun fst_arg -> (use_arg_then2 ("h", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("t", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subseq_cat", [subseq_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subseq_refl", [subseq_refl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma subseq_delete1 *)
let subseq_delete1 = Sections.section_proof ["x";"s"]
`subseq (delete1 x s) s`
[
(((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subseq_delete_at", [subseq_delete_at]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_delete_at *)
let mem_delete_at = Sections.section_proof ["i";"s";"y"]
`y <- delete_at i s ==> y <- s`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("mem_subseq", [mem_subseq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (DISCH_THEN apply_tac) THEN (((use_arg_then2 ("subseq_delete_at", [subseq_delete_at])) (disch_tac [])) THEN (clear_assumption "subseq_delete_at") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma mem_delete1 *)
let mem_delete1 = Sections.section_proof ["x";"y";"s"]
`y <- delete1 x s ==> y <- s`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("mem_subseq", [mem_subseq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (DISCH_THEN apply_tac) THEN (((use_arg_then2 ("subseq_delete1", [subseq_delete1])) (disch_tac [])) THEN (clear_assumption "subseq_delete1") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma perm_eq_delete_at *)
let perm_eq_delete_at = Sections.section_proof ["i";"s1";"s2"]
`i < sizel s1 /\ perm_eq s1 s2 ==>
perm_eq (delete_at i s1) (delete_at (indexl (nth x0 s1 i) s2) s2)`
[
((BETA_TAC THEN (case THEN ((move ["i_lt"]) THEN (move ["p_eq"])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`nth x0 s1 i`))) (term_tac (set_tac "x"))));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`x <- s2`))) (term_tac (have_gen_tac [](move ["x_s2"])))) (((((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("x_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["P"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("count_delete_at", [count_delete_at]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((use_arg_then2 ("p_eq", [])) (disch_tac [])) THEN (clear_assumption "p_eq") THEN BETA_TAC) THEN ((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("x_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_delete_at_1 *)
let perm_eq_delete_at_1 = Sections.section_proof ["i";"s1";"s2"]
`i < sizel s1 /\ perm_eq s1 s2 ==>
perm_eq (delete_at i s1) (delete1 (nth x0 s1 i) s2)`
[
((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_delete_at", [perm_eq_delete_at])) (disch_tac [])) THEN (clear_assumption "perm_eq_delete_at") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma perm_eq_delete1 *)
let perm_eq_delete1 = Sections.section_proof ["x";"s1";"s2"]
`perm_eq s1 s2 ==> perm_eq (delete1 x s1) (delete1 x s2)`
[
((THENL_ROT (-1)) ((BETA_TAC THEN (move ["p_eq"])) THEN (((fun arg_tac -> arg_tac (Arg_term (`x <- s1`))) (disch_eq_tac "mem" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac))));
(((repeat_tactic 1 9 (((use_arg_then2 ("not_mem_delete1", [not_mem_delete1]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["P"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("count_delete1", [count_delete1]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac))));
((((use_arg_then2 ("p_eq", [])) (disch_tac [])) THEN (clear_assumption "p_eq") THEN BETA_TAC) THEN ((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_cons_delete_at *)
let perm_eq_cons_delete_at = Sections.section_proof ["i";"s"]
`i < sizel s ==> perm_eq (nth x0 s i :: delete_at i s) s`
[
((BETA_TAC THEN (move ["i_lt"])) THEN ((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["P"])) THEN ((((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_delete_at", [count_delete_at]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
((THENL_LAST) (((fun arg_tac -> arg_tac (Arg_term (`P _`))) (disch_eq_tac "Px" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("subn0", [subn0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`0 < count P s`))) (term_tac (have_gen_tac []ALL_TAC)))) ((arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("has_count", [has_count]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((fun arg_tac -> arg_tac (Arg_term (`nth x0 s i`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("Px", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("MEM_EL", [MEM_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma perm_eq_cons_delete1 *)
let perm_eq_cons_delete1 = Sections.section_proof ["x";"s"]
`x <- s ==> perm_eq (x :: delete1 x s) s`
[
((use_arg_then2 ("perm_eq_cons_delete_at", [perm_eq_cons_delete_at])) (fun arg -> thm_tac MP_TAC arg THEN (move ["th"])));
((BETA_TAC THEN (move ["xs"])) THEN ((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("nth_index", [nth_index])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("th", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_delete_at *)
let nth_delete_at = Sections.section_proof ["i";"s";"k"]
`nth x0 (delete_at k s) i = nth x0 s (if i < k then i else SUC i)`
[
((((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("k", [])) (disch_tac [])) THEN (clear_assumption "k") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IHs"]))]) THEN ((THENL) case [ALL_TAC; (move ["k"])]) THEN (move ["i"])) THEN ((((use_arg_then2 ("delete_at", [delete_at]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN case) [ALL_TAC; (move ["i"])]) THEN ((((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("fun_if", [fun_if]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_delete1 *)
let nth_delete1 = Sections.section_proof ["x0";"x";"s";"i"]
`nth x0 (delete1 x s) i = nth x0 s (if i < indexl x s then i else SUC i)`
[
(((((use_arg_then2 ("delete1_eq_at", [delete1_eq_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_delete_at", [nth_delete_at]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma EL_delete_at *)
let EL_delete_at = Sections.section_proof ["i";"k";"s"]
`i < sizel (delete_at k s) ==>
EL i (delete_at k s) = EL (if i < k then i else SUC i) s`
[
(((use_arg_then2 ("size_delete_at", [size_delete_at]))(thm_tac (new_rewrite [] []))));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`k < sizel s`))) (disch_eq_tac "k_lt" [])) THEN case THEN (simp_tac) THEN (move ["i_lt"]) THEN (process_fst_eq_tac)));
(((((use_arg_then2 ("delete_at_eq_imp", [delete_at_eq_imp]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((use_arg_then2 ("perm_eq_cons_delete_at", [perm_eq_cons_delete_at])) (fun arg -> thm_tac MP_TAC arg THEN (move ["th"])));
((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_delete_at", [size_delete_at]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("k_lt", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
(((((use_arg_then2 ("nth_delete_at", [nth_delete_at]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma uniq_delete_at *)
let uniq_delete_at = Sections.section_proof ["i";"s"]
`uniq s ==> uniq (delete_at i s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("subseq_uniq", [subseq_uniq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (DISCH_THEN apply_tac) THEN ((use_arg_then2 ("subseq_delete_at", [subseq_delete_at])) (thm_tac apply_tac)) THEN (done_tac));
];;
(* Lemma uniq_delete1 *)
let uniq_delete1 = Sections.section_proof ["x";"s"]
`uniq s ==> uniq (delete1 x s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("subseq_uniq", [subseq_uniq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (DISCH_THEN apply_tac) THEN ((use_arg_then2 ("subseq_delete1", [subseq_delete1])) (thm_tac apply_tac)) THEN (done_tac));
];;
(* Lemma mem_delete1_uniq *)
let mem_delete1_uniq = Sections.section_proof ["x";"s"]
`uniq s /\ x <- s ==> (!y. y <- delete1 x s <=> ~(y = x) /\ y <- s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN (((((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL uniq)))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ALL_TAC) THEN (case THEN ((move ["h_mem"]) THEN (move ["uniq_t"])))));
(((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((BETA_TAC THEN (move ["y"])) THEN ((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (split_tac));
((BETA_TAC THEN (move ["y_mem"])) THEN ((((use_arg_then2 ("y_mem", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (((use_arg_then2 ("h_mem", [])) (disch_tac [])) THEN (clear_assumption "h_mem") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((((use_arg_then2 ("andb_orr", [andb_orr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andNb", [andNb]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orFb", [orFb]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
((BETA_TAC THEN (move ["x_mem"]) THEN (move ["y"])) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`y = h`))) (disch_eq_tac "eq2" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac)));
((((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section Delete *)
let delete1_eq_at = Sections.finalize_theorem delete1_eq_at;;
let delete1_hd = Sections.finalize_theorem delete1_hd;;
let count_delete_at = Sections.finalize_theorem count_delete_at;;
let count_delete1 = Sections.finalize_theorem count_delete1;;
let delete_at_eq = Sections.finalize_theorem delete_at_eq;;
let delete_at_eq_imp = Sections.finalize_theorem delete_at_eq_imp;;
let not_mem_delete1 = Sections.finalize_theorem not_mem_delete1;;
let size_delete_at = Sections.finalize_theorem size_delete_at;;
let size_delete1 = Sections.finalize_theorem size_delete1;;
let subseq_delete_at = Sections.finalize_theorem subseq_delete_at;;
let subseq_delete1 = Sections.finalize_theorem subseq_delete1;;
let mem_delete_at = Sections.finalize_theorem mem_delete_at;;
let mem_delete1 = Sections.finalize_theorem mem_delete1;;
let perm_eq_delete_at = Sections.finalize_theorem perm_eq_delete_at;;
let perm_eq_delete_at_1 = Sections.finalize_theorem perm_eq_delete_at_1;;
let perm_eq_delete1 = Sections.finalize_theorem perm_eq_delete1;;
let perm_eq_cons_delete_at = Sections.finalize_theorem perm_eq_cons_delete_at;;
let perm_eq_cons_delete1 = Sections.finalize_theorem perm_eq_cons_delete1;;
let nth_delete_at = Sections.finalize_theorem nth_delete_at;;
let nth_delete1 = Sections.finalize_theorem nth_delete1;;
let EL_delete_at = Sections.finalize_theorem EL_delete_at;;
let uniq_delete_at = Sections.finalize_theorem uniq_delete_at;;
let uniq_delete1 = Sections.finalize_theorem uniq_delete1;;
let mem_delete1_uniq = Sections.finalize_theorem mem_delete1_uniq;;
Sections.end_section "Delete";;
(* Section ListsAndSets *)
Sections.begin_section "ListsAndSets";;
(* Lemma list_of_empty_set *)
let list_of_empty_set = Sections.section_proof []
`list_of_set {} = []`
[
(((((use_arg_then2 ("LENGTH_EQ_NIL", [LENGTH_EQ_NIL]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("LENGTH_LIST_OF_SET", [LENGTH_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("CARD_CLAUSES", [CARD_CLAUSES]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("FINITE_EMPTY", [FINITE_EMPTY]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma set_of_list_subseq *)
let set_of_list_subseq = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> set_of_list s1 SUBSET set_of_list s2`
[
(((((use_arg_then2 ("SUBSET", [SUBSET]))(thm_tac (new_rewrite [] [])))) THEN (move ["s12"]) THEN (move ["x"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (move ["mem"])) THEN (((fun arg_tac -> (use_arg_then2 ("mem_subseq", [mem_subseq])) (fun fst_arg -> (use_arg_then2 ("s12", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma set_of_list_filter *)
let set_of_list_filter = Sections.section_proof ["P";"s"]
`set_of_list (filter P s) = {x | MEM x s /\ P x}`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("set_of_list", [set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("EMPTY_GSPEC", [EMPTY_GSPEC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((fun arg_tac -> arg_tac (Arg_term (`P h`))) (disch_eq_tac "c" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL set_of_list)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("c", [])) (disch_tac [])) THEN (clear_assumption "c") THEN BETA_TAC) THEN (SET_TAC[]) THEN (done_tac));
((((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("c", [])) (disch_tac [])) THEN (clear_assumption "c") THEN BETA_TAC) THEN (SET_TAC[]) THEN (done_tac));
];;
(* Lemma set_of_list_undup *)
let set_of_list_undup = Sections.section_proof ["s"]
`set_of_list (undup s) = set_of_list s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
((((fun arg_tac -> arg_tac (Arg_term (`MEM h t`))) (disch_eq_tac "mem_h" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN ((repeat_tactic 1 9 (((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL set_of_list)))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ABSORPTION", [ABSORPTION]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma set_of_list_flatten *)
let set_of_list_flatten = Sections.section_proof ["s"]
`set_of_list (flatten s) = UNIONS {set_of_list l | MEM l s}`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((((use_arg_then2 ("flatten", [flatten]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("set_of_list", [set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (SET_TAC[]) THEN (done_tac));
(((((use_arg_then2 ("flatten", [flatten]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("APPEND_cat", [APPEND_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("SET_OF_LIST_APPEND", [SET_OF_LIST_APPEND]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] []))))) THEN (SET_TAC[]) THEN (done_tac));
];;
(* Lemma uniq_list_of_set *)
let uniq_list_of_set = Sections.section_proof ["s"]
`FINITE s ==> uniq (list_of_set s)`
[
((BETA_TAC THEN (move ["fin_s"])) THEN (((use_arg_then2 ("count_mem_uniq", [count_mem_uniq])) (thm_tac apply_tac)) THEN (move ["x"])));
((((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`x IN s`))) (disch_eq_tac "xs" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
((((((use_arg_then2 ("count0", [count0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (move ["y"])) THEN (((((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["ys"])));
((((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`list_of_set s`))) (term_tac (set_tac "l")));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`x <- l`))) (term_tac (have_gen_tac [](move ["xl"])))) (((((use_arg_then2 ("l_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`0 < sizel l`))) (term_tac (have_gen_tac [](move ["l_gt0"])))) ((((use_arg_then2 ("xl", [])) (disch_tac [])) THEN (clear_assumption "xl") THEN BETA_TAC) THEN ((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_find", [has_find]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac)));
(((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`count (predC (pred1 x)) l = sizel l - 1`))) (term_tac (have_gen_tac []ALL_TAC))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("count_predC", [count_predC])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`pred1 x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("l", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN ((use_arg_then2 ("xl", [])) (disch_tac [])) THEN (clear_assumption "xl") THEN BETA_TAC) THEN ((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] [])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`filter _1 l`))) (term_tac (set_tac "l2"))));
((((use_arg_then2 ("anti_leq", [anti_leq])) (disch_tac [])) THEN (clear_assumption "anti_leq") THEN (DISCH_THEN apply_tac)) THEN (split_tac));
((((use_arg_then2 ("l2_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((THENL) (((use_arg_then2 ("xl", [])) (disch_tac [])) THEN (clear_assumption "xl") THEN ((use_arg_then2 ("l", [])) (disch_tac [])) THEN (clear_assumption "l") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("filter", [filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("predC", [predC]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("pred1", [pred1]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((THENL) case [((((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)); (move ["mem_x"])]);
((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_filter", [count_filter]))(gsym_then (thm_tac (new_rewrite [] []))))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("count_size", [count_size])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`predC (pred1 x)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("t", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`0 < sizel t`))) (term_tac (have_gen_tac []ALL_TAC))) ((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN BETA_TAC) THEN ((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_find", [has_find]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac)));
((((fun arg_tac -> arg_tac (Arg_term (`h = x`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("IH", [])) (fun fst_arg -> (use_arg_then2 ("mem_x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("LENGTH_LIST_OF_SET", [LENGTH_LIST_OF_SET])) (fun fst_arg -> (use_arg_then2 ("fin_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (((((use_arg_then2 ("l_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (move ["size_eq"])));
((((use_arg_then2 ("leq_trans", [leq_trans])) (disch_tac [])) THEN (clear_assumption "leq_trans") THEN (DISCH_THEN apply_tac)) THEN ((fun arg_tac -> arg_tac (Arg_term (`CARD (set_of_list l DELETE x)`))) (term_tac exists_tac)));
((((use_arg_then2 ("CARD_DELETE", [CARD_DELETE]))(thm_tac (new_rewrite [1] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_SET_OF_LIST", [FINITE_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("xl", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
((((use_arg_then2 ("l_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("SET_OF_LIST_OF_SET", [SET_OF_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("l_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] [])))));
(((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`set_of_list l2 = s DELETE x`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))))));
(((((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("CARD_SET_OF_LIST_LE", [CARD_SET_OF_LIST_LE]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("EXTENSION", [EXTENSION]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_DELETE", [IN_DELETE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (move ["y"]));
(((((use_arg_then2 ("l2_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_filter", [mem_filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("l_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_list_of_set *)
let perm_eq_list_of_set = Sections.section_proof ["l";"s"]
`FINITE s ==>
(perm_eq l (list_of_set s) <=> sizel l = CARD s /\ (!x. x <- l <=> x IN s))`
[
((BETA_TAC THEN (move ["fin_s"])) THEN ((THENL) (split_tac) [(move ["p_eq"]); (case THEN ((move ["size_eq"]) THEN (move ["mem_eq"])))]));
(((((fun arg_tac -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LENGTH_LIST_OF_SET", [LENGTH_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac))) THEN (move ["y"]));
(((((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_LAST) ((((use_arg_then2 ("uniq_perm_eq", [uniq_perm_eq]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (split_tac) [ALL_TAC; (move ["y"])])) ((((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("uniq_list_of_set", [uniq_list_of_set]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] [])))));
(((((fun arg_tac -> (use_arg_then2 ("uniq_size_uniq", [uniq_size_uniq])) (fun fst_arg -> (fun arg_tac -> (use_arg_then2 ("uniq_list_of_set", [uniq_list_of_set])) (fun fst_arg -> (use_arg_then2 ("fin_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [2] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("LENGTH_LIST_OF_SET", [LENGTH_LIST_OF_SET]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (move ["y"]));
((((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma perm_eq_set_of_list *)
let perm_eq_set_of_list = Sections.section_proof ["l";"s"]
`FINITE s /\ perm_eq l (list_of_set s) ==> set_of_list l = s`
[
(BETA_TAC THEN (case THEN (move ["fin_s"])) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (move ["mem"]));
((((((use_arg_then2 ("EXTENSION", [EXTENSION]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem", []))(thm_tac (new_rewrite [] []))))) THEN (move ["x"])) THEN (((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma card_set_of_list_uniq *)
let card_set_of_list_uniq = Sections.section_proof ["l"]
`uniq l ==> CARD (set_of_list l) = sizel l`
[
((BETA_TAC THEN (move ["uniq_l"])) THEN (((use_arg_then2 ("anti_leq", [anti_leq])) (disch_tac [])) THEN (clear_assumption "anti_leq") THEN (DISCH_THEN apply_tac)) THEN ((((use_arg_then2 ("size", [size]))(thm_tac (new_rewrite [1] [])))) THEN (((use_arg_then2 ("CARD_SET_OF_LIST_LE", [CARD_SET_OF_LIST_LE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("LENGTH_LIST_OF_SET", [LENGTH_LIST_OF_SET]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_SET_OF_LIST", [FINITE_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("uniq_leq_size", [uniq_leq_size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("uniq_l", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] []))))) THEN (move ["x"]) THEN (move ["mem_x"]));
(((((use_arg_then2 ("MEM_LIST_OF_SET", [MEM_LIST_OF_SET]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_SET_OF_LIST", [FINITE_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma BIJ_from_lists *)
let BIJ_from_lists = Sections.section_proof ["s1";"s2"]
`uniq s1 /\ uniq s2 /\ sizel s1 = sizel s2 ==>
BIJ (\x. EL (indexl x s1) s2) (set_of_list s1) (set_of_list s2)`
[
(BETA_TAC THEN (case THEN (move ["uniq_s1"])) THEN (case THEN (move ["uniq_s2"])) THEN (move ["size_eq"]));
(((((use_arg_then2 ("BIJ", [BIJ]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("INJ", [INJ]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("SURJ", [SURJ]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (repeat_tactic 1 9 (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))))) THEN (split_tac));
((THENL) (split_tac) [((move ["x"]) THEN (move ["mem_x"])); ((move ["x"]) THEN (move ["y"]) THEN (case THEN (move ["xs1"])) THEN (case THEN (move ["ys2"])))]);
(((((use_arg_then2 ("MEM_EL", [MEM_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
(((((use_arg_then2 ("nth_uniq", [nth_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("uniq_index_inj", [uniq_index_inj]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_FIRST) ((split_tac) THEN (move ["x"]) THEN (move ["mem_x"])) (((((use_arg_then2 ("MEM_EL", [MEM_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`nth ((@)UNIV) s1 (indexl x s2)`))) (term_tac exists_tac));
((((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("EL_index", [EL_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma set_of_list_iota *)
let set_of_list_iota = Sections.section_proof ["m";"n"]
`set_of_list (iota m n) = if n = 0 then {} else m..m + n - 1`
[
(((((use_arg_then2 ("EXTENSION", [EXTENSION]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_iota", [mem_iota]))(thm_tac (new_rewrite [] []))))) THEN (move ["i"]));
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN case) [ALL_TAC; (move ["n"])]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((fun arg_tac ->(use_arg_then2 ("NOT_IN_EMPTY", [NOT_IN_EMPTY]))(fun tmp_arg1 -> (use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma perm_eq_set_of_list_eq *)
let perm_eq_set_of_list_eq = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> set_of_list s1 = set_of_list s2`
[
((((((use_arg_then2 ("EXTENSION", [EXTENSION]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))))) THEN (move ["perm"]) THEN (move ["x"])) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section ListsAndSets *)
let list_of_empty_set = Sections.finalize_theorem list_of_empty_set;;
let set_of_list_subseq = Sections.finalize_theorem set_of_list_subseq;;
let set_of_list_filter = Sections.finalize_theorem set_of_list_filter;;
let set_of_list_undup = Sections.finalize_theorem set_of_list_undup;;
let set_of_list_flatten = Sections.finalize_theorem set_of_list_flatten;;
let uniq_list_of_set = Sections.finalize_theorem uniq_list_of_set;;
let perm_eq_list_of_set = Sections.finalize_theorem perm_eq_list_of_set;;
let perm_eq_set_of_list = Sections.finalize_theorem perm_eq_set_of_list;;
let card_set_of_list_uniq = Sections.finalize_theorem card_set_of_list_uniq;;
let BIJ_from_lists = Sections.finalize_theorem BIJ_from_lists;;
let set_of_list_iota = Sections.finalize_theorem set_of_list_iota;;
let perm_eq_set_of_list_eq = Sections.finalize_theorem perm_eq_set_of_list_eq;;
Sections.end_section "ListsAndSets";;
(* Section ListSum *)
Sections.begin_section "ListSum";;
(Sections.add_section_type (mk_var ("f", (`:A->real`))));;
(* Lemma list_sum_nil *)
let list_sum_nil = Sections.section_proof ["f"]
`list_sum [] f = &0`
[
(((((use_arg_then2 ("list_sum", [list_sum]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_cons *)
let list_sum_cons = Sections.section_proof ["h";"t";"f"]
`list_sum (h :: t) f = f h + list_sum t f`
[
(((((use_arg_then2 ("list_sum", [list_sum]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("list_sum", [list_sum]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma list_sum_cat *)
let list_sum_cat = Sections.section_proof ["s1";"s2";"f"]
`list_sum (s1 ++ s2) f = list_sum s1 f + list_sum s2 f`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_ADD_LID", [REAL_ADD_LID]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_ADD_ASSOC", [REAL_ADD_ASSOC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_add *)
let list_sum_add = Sections.section_proof ["s";"f1";"f2"]
`list_sum s (\x. f1 x + f2 x) = list_sum s f1 + list_sum s f2`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_ADD_LID", [REAL_ADD_LID]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)));
((((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_lmul *)
let list_sum_lmul = Sections.section_proof ["s";"f";"c"]
`list_sum s (\x. c * f x) = c * list_sum s f`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_MUL_RZERO", [REAL_MUL_RZERO]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_rmul *)
let list_sum_rmul = Sections.section_proof ["s";"f";"c"]
`list_sum s (\x. f x * c) = c * list_sum s f`
[
(((((use_arg_then2 ("list_sum_lmul", [list_sum_lmul]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("REAL_MUL_SYM", [REAL_MUL_SYM]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_delete1 *)
let list_sum_delete1 = Sections.section_proof ["x";"s";"f"]
`list_sum (delete1 x s) f = list_sum s f - if x <- s then f x else &0`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_SUB_RZERO", [REAL_SUB_RZERO]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`x = h`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac)));
(((repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_perm_eq *)
let list_sum_perm_eq = Sections.section_proof ["s1";"s2";"f"]
`perm_eq s1 s2 ==> list_sum s1 f = list_sum s2 f`
[
((THENL_FIRST) (((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN (move ["s2"])) (((((use_arg_then2 ("perm_eq0l", [perm_eq0l]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((BETA_TAC THEN (move ["p_eq"])) THEN (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))));
((THENL_ROT (-1)) (((fun arg_tac -> (use_arg_then2 ("IH", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`delete1 h s2`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("list_sum_delete1", [list_sum_delete1]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("p_eq", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`t = delete1 h (h :: t)`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))))) ((((use_arg_then2 ("perm_eq_delete1", [perm_eq_delete1]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("delete1", [delete1]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma list_sum_nseq *)
let list_sum_nseq = Sections.section_proof ["x";"n";"f"]
`list_sum (nseq n x) f = &n * f x`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ncons", [ncons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("iter", [iter]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_MUL_LZERO", [REAL_MUL_LZERO]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nseq", [nseq]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ADD1", [ADD1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_OF_NUM_ADD", [REAL_OF_NUM_ADD]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_eq *)
let list_sum_eq = Sections.section_proof ["s";"f";"g"]
`(!x. x <- s ==> f x = g x) ==> list_sum s f = list_sum s g`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN (((repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))) THEN (move ["eq"])));
((THENL_FIRST) ((repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (congr_tac (`_1 + _2:real`))) ((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (move ["x"]) THEN (move ["mem_x"])) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma list_sum_nth_eq *)
let list_sum_nth_eq = Sections.section_proof ["x1";"x2";"s1";"s2";"f";"g"]
`sizel s1 = sizel s2 /\
(!i. i < sizel s1 ==> f (nth x1 s1 i) = g (nth x2 s2 i)) ==>
list_sum s1 f = list_sum s2 g`
[
((((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((THENL) case [ALL_TAC; ((move ["a"]) THEN (move ["b"]))])) THEN ((repeat_tactic 1 9 (((fun arg_tac ->(use_arg_then2 ("size_cons", [size_cons]))(fun tmp_arg1 -> (use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] [])))))) THEN (TRY ((arith_tac))));
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["size_eq"])) THEN (move ["el_eq"])) THEN (repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))));
((THENL_FIRST) (congr_tac (`_1 + _2:real`)) ((((fun arg_tac -> (use_arg_then2 ("el_eq", [])) (fun fst_arg -> (fun arg_tac -> (use_arg_then2 ("gtS0", [gtS0])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel t`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((fun arg_tac -> (use_arg_then2 ("IH", [])) (fun fst_arg -> (use_arg_then2 ("b", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["i_lt"]));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("iffRL", [iffRL])) (fun fst_arg -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltSS", [ltSS])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel t`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("i_lt", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("el_eq", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_const *)
let list_sum_const = Sections.section_proof ["s";"c"]
`list_sum s (\x. c) = &(sizel s) * c`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_MUL_LZERO", [REAL_MUL_LZERO]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ADD1", [ADD1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_OF_NUM_ADD", [REAL_OF_NUM_ADD]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_eq0 *)
let list_sum_eq0 = Sections.section_proof ["s";"f"]
`(!x. x <- s ==> f x = &0) ==> list_sum s f = &0`
[
((BETA_TAC THEN (move ["eq0"])) THEN ((((fun arg_tac -> (use_arg_then2 ("REAL_MUL_RZERO", [REAL_MUL_RZERO])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`&(sizel s)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("list_sum_const", [list_sum_const]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((((use_arg_then2 ("list_sum_eq", [list_sum_eq])) (disch_tac [])) THEN (clear_assumption "list_sum_eq") THEN (DISCH_THEN apply_tac) THEN (move ["x"]) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("eq0", [])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (done_tac));
];;
(* Lemma list_sum_ge0 *)
let list_sum_ge0 = Sections.section_proof ["s";"f"]
`(!x. x <- s ==> &0 <= f x) ==> &0 <= list_sum s f`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((fun arg_tac ->(use_arg_then2 ("list_sum_nil", [list_sum_nil]))(fun tmp_arg1 -> (use_arg_then2 ("list_sum_cons", [list_sum_cons]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_LE_REFL", [REAL_LE_REFL]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((THENL_LAST) (((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (move ["f_ge0"])) THEN ((((use_arg_then2 ("REAL_LE_ADD", [REAL_LE_ADD]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] []))))))) (((use_arg_then2 ("f_ge0", [])) (disch_tac [])) THEN (clear_assumption "f_ge0") THEN (exact_tac)));
((BETA_TAC THEN (move ["x"]) THEN (move ["mem_x"])) THEN (((use_arg_then2 ("f_ge0", [])) (disch_tac [])) THEN (clear_assumption "f_ge0") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma list_sum_nth_le2 *)
let list_sum_nth_le2 = Sections.section_proof ["x1";"x2";"s";"t";"f";"g"]
`sizel t = sizel s /\
(!i. i < sizel s ==> f (nth x1 s i) <= g (nth x2 t i)) ==>
list_sum s f <= list_sum t g`
[
((((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h1"]) THEN (move ["t1"]) THEN (move ["IH1"]))]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t2"]))])) THEN ((repeat_tactic 1 9 (((fun arg_tac ->(use_arg_then2 ("list_sum_nil", [list_sum_nil]))(fun tmp_arg1 -> (use_arg_then2 ("list_sum_cons", [list_sum_cons]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("REAL_LE_REFL", [REAL_LE_REFL]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (TRY ((arith_tac))));
((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["size_eq"])) THEN (move ["h"]));
((((use_arg_then2 ("REAL_LE_ADD2", [REAL_LE_ADD2]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IH1", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_eq", []))(thm_tac (new_rewrite [] []))))) THEN (simp_tac));
((BETA_TAC THEN (move ["i"]) THEN (move ["i_lt"])) THEN (((fun arg_tac -> (use_arg_then2 ("h", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`SUC i`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_lt", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("h", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma list_sum_undup *)
let list_sum_undup = Sections.section_proof ["s";"f"]
`list_sum s f = list_sum (undup s) (\x. &(count (pred1 x) s) * f x)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_OF_NUM_ADD", [REAL_OF_NUM_ADD]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("REAL_ADD_RDISTRIB", [REAL_ADD_RDISTRIB]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_add", [list_sum_add]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`h <- t`))) (disch_eq_tac "mem_h" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((((use_arg_then2 ("IH", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((congr_tac (`_1 + _2:real`)) THEN ((TRY done_tac))));
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("list_sum_perm_eq", [list_sum_perm_eq])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`undup t`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`h :: delete1 h (undup t)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))));
(((((use_arg_then2 ("perm_eq_sym", [perm_eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_cons_delete1", [perm_eq_cons_delete1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [1] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("REAL_MUL_LID", [REAL_MUL_LID]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("REAL_ADD_RID", [REAL_ADD_RID])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`f h`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("REAL_EQ_ADD_LCANCEL", [REAL_EQ_ADD_LCANCEL]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_eq0", [list_sum_eq0]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (move ["x"]));
(((((use_arg_then2 ("mem_delete1_uniq", [mem_delete1_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("undup_uniq", [undup_uniq]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (move ["h"]) THEN (simp_tac));
(((((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("h", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((use_arg_then2 ("REAL_MUL_LZERO", [REAL_MUL_LZERO]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((repeat_tactic 1 9 (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((use_arg_then2 ("IH", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [1] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("REAL_MUL_LID", [REAL_MUL_LID]))(thm_tac (new_rewrite [] [])))));
((repeat_tactic 1 9 (((use_arg_then2 ("REAL_ADD_ASSOC", [REAL_ADD_ASSOC]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("REAL_EQ_ADD_RCANCEL", [REAL_EQ_ADD_RCANCEL]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`count (pred1 h) t = 0`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))));
((((use_arg_then2 ("mem_h", [])) (disch_tac [])) THEN (clear_assumption "mem_h") THEN BETA_TAC) THEN ((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("REAL_MUL_LZERO", [REAL_MUL_LZERO]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_ADD_RID", [REAL_ADD_RID]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("REAL_ADD_RID", [REAL_ADD_RID])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`f h`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("REAL_EQ_ADD_LCANCEL", [REAL_EQ_ADD_LCANCEL]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_eq0", [list_sum_eq0]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] []))))) THEN (move ["x"]) THEN (move ["mem_x"]) THEN (simp_tac));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`~(h = x)`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))))) (((simp_tac) THEN (((use_arg_then2 ("REAL_MUL_LZERO", [REAL_MUL_LZERO]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("mem_h", [])) (disch_tac [])) THEN (clear_assumption "mem_h") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_set_of_list *)
let list_sum_set_of_list = Sections.section_proof ["s";"f"]
`uniq s ==> list_sum s f = sum (set_of_list s) f`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("set_of_list", [set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("SUM_CLAUSES", [SUM_CLAUSES]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_SET_OF_LIST", [FINITE_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("uniq", [uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IH", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_list_of_set *)
let list_sum_list_of_set = Sections.section_proof ["s";"f"]
`FINITE s ==> list_sum (list_of_set s) f = sum s f`
[
((BETA_TAC THEN (move ["fin_s"])) THEN ((((use_arg_then2 ("list_sum_set_of_list", [list_sum_set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("uniq_list_of_set", [uniq_list_of_set]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("SET_OF_LIST_OF_SET", [SET_OF_LIST_OF_SET]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_nth *)
let list_sum_nth = Sections.section_proof ["x0";"s";"f"]
`list_sum s f = list_sum (iota 0 (sizel s)) (\i. f (nth x0 s i))`
[
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("list_sum_nth_eq", [list_sum_nth_eq])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac));
(((((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["i_lt"]));
(((((use_arg_then2 ("nth_iota", [nth_iota]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_EL *)
let list_sum_EL = Sections.section_proof ["s";"f"]
`~(s = []) ==> list_sum s f = sum (0..sizel s - 1) (\i. f (EL i s))`
[
((((use_arg_then2 ("size_eq0", [size_eq0]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (move ["size_neq"]));
((((fun arg_tac -> (use_arg_then2 ("list_sum_nth", [list_sum_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(@)UNIV`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_set_of_list", [list_sum_set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("iota_uniq", [iota_uniq]))(thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("set_of_list_iota", [set_of_list_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_neq", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))));
(((use_arg_then2 ("SUM_EQ", [SUM_EQ])) (thm_tac apply_tac)) THEN ((((use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(thm_tac (new_rewrite [] [])))) THEN (move ["i"]) THEN (move ["ineqs"]) THEN (simp_tac)));
(((((use_arg_then2 ("EL_nth", [EL_nth]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("size_neq", [])) (disch_tac [])) THEN (clear_assumption "size_neq") THEN ((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma list_sum_EL_alt *)
let list_sum_EL_alt = Sections.section_proof ["s";"f"]
`list_sum s f = sum (1..sizel s) (\i. f (EL (i - 1) s))`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN (((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("size_cons", [size_cons]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL SUM_CLAUSES_NUMSEG)))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [1] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ADD1", [ADD1]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("SUM_OFFSET", [SUM_OFFSET]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_EL", [list_sum_EL]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))));
(((use_arg_then2 ("SUM_EQ", [SUM_EQ])) (thm_tac apply_tac)) THEN ((((use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(thm_tac (new_rewrite [] [])))) THEN (move ["i"]) THEN (move ["ineqs"]) THEN (simp_tac)));
(((((use_arg_then2 ("ADD1", [ADD1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sum_iota *)
let list_sum_iota = Sections.section_proof ["m";"n";"g"]
`list_sum (iota m n) g = if (n = 0) then &0 else sum (m..m + n - 1) g`
[
((((use_arg_then2 ("list_sum_set_of_list", [list_sum_set_of_list]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("iota_uniq", [iota_uniq]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("set_of_list_iota", [set_of_list_iota]))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> arg_tac (Arg_term (`n = 0`))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (((use_arg_then2 ("SUM_CLAUSES", [SUM_CLAUSES]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma count_eq_list_sum *)
let count_eq_list_sum = Sections.section_proof ["a";"s"]
`&(count a s) = list_sum s (\x. if a x then &1 else &0)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN ((((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac ->(use_arg_then2 ("list_sum_nil", [list_sum_nil]))(fun tmp_arg1 -> (use_arg_then2 ("list_sum_cons", [list_sum_cons]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("REAL_OF_NUM_ADD", [REAL_OF_NUM_ADD]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("fun_if", [fun_if]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_eq_nsum *)
let count_eq_nsum = Sections.section_proof ["a";"s"]
`~(s = []) ==> count a s = nsum (0..sizel s - 1) (\i. if a (EL i s) then 1 else 0)`
[
(BETA_TAC THEN (move ["s_n_nil"]));
(((((use_arg_then2 ("REAL_OF_NUM_EQ", [REAL_OF_NUM_EQ]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("count_eq_list_sum", [count_eq_list_sum]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_EL", [list_sum_EL]))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("REAL_OF_NUM_SUM", [REAL_OF_NUM_SUM]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_NUMSEG", [FINITE_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("fun_if", [fun_if]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_eq_list_sum_iota *)
let count_eq_list_sum_iota = Sections.section_proof ["x0";"a";"s"]
`&(count a s) = list_sum (iota 0 (sizel s)) (\i. if a (nth x0 s i) then &1 else &0)`
[
((((use_arg_then2 ("count_eq_list_sum", [count_eq_list_sum]))(thm_tac (new_rewrite [] [])))) THEN ((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("list_sum_nth_eq", [list_sum_nth_eq])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac apply_tac)));
((((((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["i_lt"])) THEN ((((use_arg_then2 ("nth_iota", [nth_iota]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section ListSum *)
let list_sum_nil = Sections.finalize_theorem list_sum_nil;;
let list_sum_cons = Sections.finalize_theorem list_sum_cons;;
let list_sum_cat = Sections.finalize_theorem list_sum_cat;;
let list_sum_add = Sections.finalize_theorem list_sum_add;;
let list_sum_lmul = Sections.finalize_theorem list_sum_lmul;;
let list_sum_rmul = Sections.finalize_theorem list_sum_rmul;;
let list_sum_delete1 = Sections.finalize_theorem list_sum_delete1;;
let list_sum_perm_eq = Sections.finalize_theorem list_sum_perm_eq;;
let list_sum_nseq = Sections.finalize_theorem list_sum_nseq;;
let list_sum_eq = Sections.finalize_theorem list_sum_eq;;
let list_sum_nth_eq = Sections.finalize_theorem list_sum_nth_eq;;
let list_sum_const = Sections.finalize_theorem list_sum_const;;
let list_sum_eq0 = Sections.finalize_theorem list_sum_eq0;;
let list_sum_ge0 = Sections.finalize_theorem list_sum_ge0;;
let list_sum_nth_le2 = Sections.finalize_theorem list_sum_nth_le2;;
let list_sum_undup = Sections.finalize_theorem list_sum_undup;;
let list_sum_set_of_list = Sections.finalize_theorem list_sum_set_of_list;;
let list_sum_list_of_set = Sections.finalize_theorem list_sum_list_of_set;;
let list_sum_nth = Sections.finalize_theorem list_sum_nth;;
let list_sum_EL = Sections.finalize_theorem list_sum_EL;;
let list_sum_EL_alt = Sections.finalize_theorem list_sum_EL_alt;;
let list_sum_iota = Sections.finalize_theorem list_sum_iota;;
let count_eq_list_sum = Sections.finalize_theorem count_eq_list_sum;;
let count_eq_nsum = Sections.finalize_theorem count_eq_nsum;;
let count_eq_list_sum_iota = Sections.finalize_theorem count_eq_list_sum_iota;;
Sections.end_section "ListSum";;
(* Section ListSumn *)
Sections.begin_section "ListSumn";;
(Sections.add_section_type (mk_var ("f", (`:A->num`))));;
(* Lemma list_sumn_nil *)
let list_sumn_nil = Sections.section_proof ["f"]
`list_sumn [] f = 0`
[
(((((use_arg_then2 ("list_sumn", [list_sumn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma list_sumn_cons *)
let list_sumn_cons = Sections.section_proof ["h";"t";"f"]
`list_sumn (CONS h t) f = f h + list_sumn t f`
[
(((((use_arg_then2 ("list_sumn", [list_sumn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sumn", [list_sumn]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma list_sum_eq_list_sumn *)
let list_sum_eq_list_sumn = Sections.section_proof ["s";"f"]
`list_sum s ((&) o f) = &(list_sumn s f)`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) (((((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sumn_nil", [list_sumn_nil]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("list_sumn_cons", [list_sumn_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sum_cons", [list_sum_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("REAL_OF_NUM_ADD", [REAL_OF_NUM_ADD]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("o_THM", [o_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_flatten *)
let count_flatten = Sections.section_proof ["s";"a"]
`count a (flatten s) = list_sumn (map (count a) s) I`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((((use_arg_then2 ("flatten", [flatten]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr", [foldr]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map", [map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sumn_nil", [list_sumn_nil]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("flatten", [flatten]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("map", [map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("list_sumn_cons", [list_sumn_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("I_THM", [I_THM]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_flatten *)
let perm_eq_flatten = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> perm_eq (flatten s1) (flatten s2)`
[
((BETA_TAC THEN (move ["perm"])) THEN ((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["a"])));
((repeat_tactic 1 9 (((use_arg_then2 ("count_flatten", [count_flatten]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("REAL_OF_NUM_EQ", [REAL_OF_NUM_EQ]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("list_sum_eq_list_sumn", [list_sum_eq_list_sumn]))(gsym_then (thm_tac (new_rewrite [] [])))))));
(((use_arg_then2 ("list_sum_perm_eq", [list_sum_perm_eq])) (thm_tac apply_tac)) THEN (((use_arg_then2 ("perm_eq_map", [perm_eq_map]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section ListSumn *)
let list_sumn_nil = Sections.finalize_theorem list_sumn_nil;;
let list_sumn_cons = Sections.finalize_theorem list_sumn_cons;;
let list_sum_eq_list_sumn = Sections.finalize_theorem list_sum_eq_list_sumn;;
let count_flatten = Sections.finalize_theorem count_flatten;;
let perm_eq_flatten = Sections.finalize_theorem perm_eq_flatten;;
Sections.end_section "ListSumn";;
(* Section PermEqPermutes *)
Sections.begin_section "PermEqPermutes";;
(Sections.add_section_var (mk_var ("x0", (`:A`))));;
(* Lemma perm_eq_bij *)
let perm_eq_bij = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==>
(?p. p permutes (0..sizel s1 - 1) /\ (!i. i < sizel s1 ==> nth x0 s2 i = nth x0 s1 (p i)))`
[
(((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["IH"]))]) THEN (move ["s2"]));
(((((use_arg_then2 ("perm_eq0l", [perm_eq0l]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`I`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("sub0n", [sub0n]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("NUMSEG_SING", [NUMSEG_SING]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("PERMUTES_SING", [PERMUTES_SING]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (move ["perm"]));
(((fun arg_tac -> (use_arg_then2 ("IH", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`delete1 h s2`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN ((use_arg_then2 ("IH", [])) (disch_tac [])) THEN (clear_assumption "IH") THEN BETA_TAC THEN (move ["_"]));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("delete1_hd", [delete1_hd])) (fun fst_arg -> (use_arg_then2 ("h", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("t", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_delete1", [perm_eq_delete1])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
(BETA_TAC THEN (case THEN (move ["q"])) THEN (case THEN (move ["perm_q"])) THEN (move ["del_eq"]));
((fun arg_tac -> arg_tac (Arg_term (`indexl h s2`))) (term_tac (set_tac "k")));
((fun arg_tac -> arg_tac (Arg_term (`\i. if sizel t < i then i else
if i = k then 0 else SUC (q (if i < k then i else i - 1))`))) (term_tac (set_tac "p")));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`h <- s2`))) (term_tac (have_gen_tac [](move ["hs2"])))) (((((fun arg_tac -> (use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k < sizel s2`))) (term_tac (have_gen_tac [](move ["k_lt"])))) (((((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`sizel t = sizel s2 - 1`))) (term_tac (have_gen_tac [](move ["size_t"])))) (((((fun arg_tac -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`i < k:num ==> p i = SUC (q i)`))) (term_tac (have_gen_tac ["i"](move ["p1"])))) (((((use_arg_then2 ("p_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_t", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`p k = 0`))) (term_tac (have_gen_tac [](move ["p2"])))) (((((use_arg_then2 ("p_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_t", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`k < i:num /\ i <= sizel t ==> p i = SUC (q (i - 1))`))) (term_tac (have_gen_tac ["i"](move ["p3"]))));
(((((use_arg_then2 ("p_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_t", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`sizel t < i ==> p i = i`))) (term_tac (have_gen_tac ["i"](move ["p4"])))) ((((((use_arg_then2 ("p_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("perm_q", [])) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("PERMUTES_FINITE_SURJECTIVE", [PERMUTES_FINITE_SURJECTIVE]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_NUMSEG", [FINITE_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)));
(BETA_TAC THEN (case THEN (move ["_"])) THEN (case THEN (move ["q_in"])) THEN (move ["q_exists"]));
(((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (split_tac));
((((use_arg_then2 ("PERMUTES_FINITE_SURJECTIVE", [PERMUTES_FINITE_SURJECTIVE]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_NUMSEG", [FINITE_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac));
((THENL_FIRST) ((THENL) (split_tac) [((move ["n"]) THEN (move ["n_le"])); ALL_TAC]) (((((use_arg_then2 ("p4", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("NOT_LE", [NOT_LE]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac)));
((THENL_ROT (-1)) ((split_tac) THEN (move ["n"]) THEN (move ["n_le"])));
(((THENL) (((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN case) [ALL_TAC; (move ["n"])]) THEN (move ["n_le"]));
(((use_arg_then2 ("k", [])) (term_tac exists_tac)) THEN ((((use_arg_then2 ("p2", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_t", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) ((((fun arg_tac -> (use_arg_then2 ("q_exists", [])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (ANTS_TAC)) ((((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(BETA_TAC THEN (case THEN (move ["m"])) THEN (case THEN (move ["m_le"])) THEN (move ["q_eq"]));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`if m < k then m else m + 1`))) (term_tac exists_tac)) THEN (split_tac)) ((((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN ((use_arg_then2 ("m_le", [])) (disch_tac [])) THEN (clear_assumption "m_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`m < k:num`))) (disch_eq_tac "m_lt_k" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((((use_arg_then2 ("p1", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("p3", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ADD1", [ADD1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("q_eq", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
((((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN ((use_arg_then2 ("m_le", [])) (disch_tac [])) THEN (clear_assumption "m_le") THEN ((use_arg_then2 ("m_lt_k", [])) (disch_tac [])) THEN (clear_assumption "m_lt_k") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL) (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltngtP", [ltngtP])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("k", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [(move ["n_lt"]); ALL_TAC]);
(((((use_arg_then2 ("p1", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN ((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN ((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN ((fun arg_tac -> (use_arg_then2 ("q_in", [])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (((use_arg_then2 ("size_t", []))(thm_tac (new_rewrite [] [])))) THEN (arith_tac) THEN (done_tac));
((THENL_LAST) ((THENL) case [(move ["k_lt"]); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) (((((use_arg_then2 ("p2", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("p3", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((fun arg_tac -> (use_arg_then2 ("q_in", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`n - 1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("leq_sub2r", [leq_sub2r]))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac))) THEN (((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN ((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
(BETA_TAC THEN (move ["i"]) THEN (move ["i_lt"]));
((THENL) (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltngtP", [ltngtP])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("k", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [(move ["i_lt_k"]); ALL_TAC]);
((THENL_FIRST) ((((fun arg_tac -> (use_arg_then2 ("del_eq", [])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (ANTS_TAC)) ((((use_arg_then2 ("size_t", [])) (disch_tac [])) THEN (clear_assumption "size_t") THEN ((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN ((use_arg_then2 ("i_lt_k", [])) (disch_tac [])) THEN (clear_assumption "i_lt_k") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("nth_delete1", [nth_delete1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("k_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_lt_k", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("COND_CLAUSES", [COND_CLAUSES]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("p1", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_LAST) ((THENL) case [(move ["k_lt_i"]); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) (((((use_arg_then2 ("p2", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((((fun arg_tac -> (use_arg_then2 ("del_eq", [])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`i - 1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (ANTS_TAC)) ((((use_arg_then2 ("k_lt_i", [])) (disch_tac [])) THEN (clear_assumption "k_lt_i") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("nth_delete1", [nth_delete1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("k_def", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `k < i ==> ~(i - 1 < k) /\ SUC (i - 1) = i`)))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("COND_CLAUSES", [COND_CLAUSES]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("p3", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("k_lt_i", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma permutes_imp_perm_eq_iota *)
let permutes_imp_perm_eq_iota = Sections.section_proof ["p";"n"]
`p permutes 0..n
==> perm_eq (mkseq p (n + 1)) (iota 0 (n + 1))`
[
(BETA_TAC THEN (move ["p_perm"]));
(((((use_arg_then2 ("uniq_perm_eq_alt", [uniq_perm_eq_alt]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (split_tac));
(((((fun arg_tac -> (use_arg_then2 ("uniq_nthP", [uniq_nthP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] []))))) THEN (move ["i"]) THEN (move ["j"]) THEN (case THEN ((move ["i_lt"]) THEN (move ["j_lt"]))));
((THENL_FIRST) ((repeat_tactic 1 9 (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) ((((use_arg_then2 ("j_lt", [])) (disch_tac [])) THEN (clear_assumption "j_lt") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((fun arg_tac -> (use_arg_then2 ("PERMUTES_INJECTIVE", [PERMUTES_INJECTIVE])) (fun fst_arg -> (use_arg_then2 ("p_perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("p_perm", [])) (disch_tac [])) THEN (clear_assumption "p_perm") THEN BETA_TAC) THEN ((((use_arg_then2 ("PERMUTES_FINITE_SURJECTIVE", [PERMUTES_FINITE_SURJECTIVE]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("FINITE_NUMSEG", [FINITE_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("IN_NUMSEG", [IN_NUMSEG]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)));
(BETA_TAC THEN (case THEN (move ["_"])) THEN (case THEN (move ["p_ineqs"])) THEN (move ["p_exists"]) THEN (move ["i"]));
(((((use_arg_then2 ("mem_iota", [mem_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM_EXISTS_EL", [MEM_EXISTS_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN ((THENL) (split_tac) [((case THEN (move ["j"])) THEN (case THEN (move ["j_lt"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))); ALL_TAC]));
((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((use_arg_then2 ("j_lt", [])) (disch_tac [])) THEN (clear_assumption "j_lt") THEN ((fun arg_tac -> (use_arg_then2 ("p_ineqs", [])) (fun fst_arg -> (use_arg_then2 ("j", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
(((((use_arg_then2 ("ADD1", [ADD1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))))) THEN (move ["i_le"]));
(((fun arg_tac -> (use_arg_then2 ("p_exists", [])) (fun fst_arg -> (use_arg_then2 ("i_le", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN (case THEN (move ["j"])) THEN (case THEN (move ["j_le"])) THEN (move ["pj_eq"]));
(((use_arg_then2 ("j", [])) (term_tac exists_tac)) THEN ((((fun arg_tac -> (use_arg_then2 ("EL_nth", [EL_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma perm_eq_iota *)
let perm_eq_iota = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==>
(?l. perm_eq l (iota 0 (sizel s1)) /\ s2 = map (nth x0 s1) l)`
[
((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]);
(((((use_arg_then2 ("perm_eq0l", [perm_eq0l]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("iota", [iota]))(thm_tac (new_rewrite [] []))))));
(((fun arg_tac -> arg_tac (Arg_term (`[]`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map", [map]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((BETA_TAC THEN (move ["perm"])) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_bij", [perm_eq_bij])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["p"])) THEN (case THEN (move ["p_perm"])) THEN (move ["nth_eq"])));
((fun arg_tac -> arg_tac (Arg_term (`sizel t`))) (term_tac (set_tac "n")));
((fun arg_tac -> arg_tac (Arg_term (`mkseq p (SUC n)`))) (term_tac exists_tac));
((((use_arg_then2 ("ADD1", [ADD1]))(thm_tac (new_rewrite [1; 2] [])))) THEN (((use_arg_then2 ("permutes_imp_perm_eq_iota", [permutes_imp_perm_eq_iota]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> (use_arg_then2 ("eq_from_nth", [eq_from_nth])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac apply_tac)) THEN ((((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)));
(BETA_TAC THEN (move ["i"]) THEN (move ["i_lt"]));
((((use_arg_then2 ("nth_map", [nth_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("x0", [])) (term_tac exists_tac)) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_permutesP *)
let perm_eq_permutesP = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 <=>
sizel s1 = sizel s2 /\
?p. p permutes 0..sizel s1 - 1 /\ (!i. i < sizel s1 ==> nth x0 s2 i = nth x0 s1 (p i))`
[
((THENL) (split_tac) [(move ["perm"]); ((case THEN (move ["size_eq"])) THEN (case THEN (move ["p"])) THEN (case THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("permutes_imp_perm_eq_iota", [permutes_imp_perm_eq_iota])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (move ["perm"]) THEN (move ["nth_eq"]))))]);
(((((fun arg_tac -> (use_arg_then2 ("perm_eq_size", [perm_eq_size])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN ((use_arg_then2 ("perm_eq_bij", [perm_eq_bij])) (thm_tac apply_tac)) THEN (done_tac));
(((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["a"])) THEN ((((use_arg_then2 ("REAL_OF_NUM_EQ", [REAL_OF_NUM_EQ]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("count_eq_list_sum_iota", [count_eq_list_sum_iota])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))))));
(((fun arg_tac -> arg_tac (Arg_term (`sizel s1 = 0`))) (disch_eq_tac "eq0" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eq0", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("iota", [iota]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("list_sum_nil", [list_sum_nil]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(in_tac ["perm"] false (((fun arg_tac -> (fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `!n. ~(n = 0) ==> n - 1 + 1 = n`))) (fun fst_arg -> (use_arg_then2 ("eq0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> (use_arg_then2 ("list_sum_perm_eq", [list_sum_perm_eq])) (fun fst_arg -> (use_arg_then2 ("perm", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("list_sum_nth_eq", [list_sum_nth_eq])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`0`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac apply_tac)));
(((((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["i_lt"]));
(((((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_iota", [nth_iota]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section PermEqPermutes *)
let perm_eq_bij = Sections.finalize_theorem perm_eq_bij;;
let permutes_imp_perm_eq_iota = Sections.finalize_theorem permutes_imp_perm_eq_iota;;
let perm_eq_iota = Sections.finalize_theorem perm_eq_iota;;
let perm_eq_permutesP = Sections.finalize_theorem perm_eq_permutesP;;
Sections.end_section "PermEqPermutes";;
(* Section BelastButlast *)
Sections.begin_section "BelastButlast";;
(* Lemma head_belast *)
let head_belast = Sections.section_proof ["x0";"x";"s"]
`0 < sizel s ==> headl x0 (belast x s) = x`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["_"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_belast *)
let nth_belast = Sections.section_proof ["x0";"s";"x";"i"]
`i < sizel s ==>
nth x0 (belast x s) i = if i = 0 then x else nth x0 s (i - 1)`
[
((((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; ((move ["i"]) THEN (move ["x"]))])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((BETA_TAC THEN (move ["x"]) THEN (move ["lt"])) THEN ((((use_arg_then2 ("nth0", [nth0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("head_belast", [head_belast]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["i_lt"]));
((((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))));
((((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN case) [ALL_TAC; (move ["j"])]) THEN (simp_tac)) THEN ((((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma take_belast *)
let take_belast = Sections.section_proof ["s";"x";"n"]
`n < sizel s /\ 0 < n ==> take n (belast x s) = x :: take (n - 1) s`
[
((((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]))]) THEN ((THENL) case [ALL_TAC; ((move ["n"]) THEN (move ["x"]))])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["ineqs"]));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN case) [(move ["_"]); ((move ["n"]) THEN (move ["ineqs"]))]) (((((use_arg_then2 ("ONE", [ONE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac)));
(((((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma butlast_eq_take *)
let butlast_eq_take = Sections.section_proof ["s"]
`butlast s = take (sizel s - 1) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN (move ["Ih"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("butlast", [butlast]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma butlast_cons *)
let butlast_cons = Sections.section_proof ["h";"t"]
`butlast (h :: t) = if t = [] then [] else h :: butlast t`
[
(((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN case) [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("butlast", [butlast]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma butlast_BUTLAST *)
let butlast_BUTLAST = Sections.section_proof []
`butlast = BUTLAST`
[
(((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] []))));
(((THENL) elim [ALL_TAC; ((move ["h"]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN (move ["Ih"]))]) THEN ((((fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL BUTLAST)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("butlast", [butlast]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_butlast *)
let size_butlast = Sections.section_proof ["s"]
`sizel (butlast s) = sizel s - 1`
[
(((((use_arg_then2 ("butlast_eq_take", [butlast_eq_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma butlast_belast *)
let butlast_belast = Sections.section_proof ["s";"x"]
`0 < sizel s ==> belast x s = x :: butlast s`
[
(((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN (move ["Ih"]) THEN (move ["x"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("ltn0", [ltn0]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("butlast", [butlast]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
((((use_arg_then2 ("Ih", [])) (disch_tac [])) THEN (clear_assumption "Ih") THEN BETA_TAC) THEN (((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma cat_butlast_last *)
let cat_butlast_last = Sections.section_proof ["x0";"s"]
`0 < sizel s ==> s = butlast s ++ [last x0 s]`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN ((THENL) case [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) THEN (move ["Ih"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((fun arg_tac ->(use_arg_then2 ("size_nil", [size_nil]))(fun tmp_arg1 -> (use_arg_then2 ("ltn0", [ltn0]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("butlast", [butlast]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))));
((((use_arg_then2 ("Ih", [])) (disch_tac [])) THEN (clear_assumption "Ih") THEN BETA_TAC) THEN (((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [1] []))))) THEN (done_tac));
];;
(* Finalization of the section BelastButlast *)
let head_belast = Sections.finalize_theorem head_belast;;
let nth_belast = Sections.finalize_theorem nth_belast;;
let take_belast = Sections.finalize_theorem take_belast;;
let butlast_eq_take = Sections.finalize_theorem butlast_eq_take;;
let butlast_cons = Sections.finalize_theorem butlast_cons;;
let butlast_BUTLAST = Sections.finalize_theorem butlast_BUTLAST;;
let size_butlast = Sections.finalize_theorem size_butlast;;
let butlast_belast = Sections.finalize_theorem butlast_belast;;
let cat_butlast_last = Sections.finalize_theorem cat_butlast_last;;
Sections.end_section "BelastButlast";;
(* Section MoreRot *)
Sections.begin_section "MoreRot";;
(* Lemma rot_nil *)
let rot_nil = Sections.section_proof ["n"]
`rot n [] = []`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop", [drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr_nil *)
let rotr_nil = Sections.section_proof ["n"]
`rotr n [] = []`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_nil", [rot_nil]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_rot *)
let perm_eq_rot = Sections.section_proof ["n";"s"]
`perm_eq (rot n s) s`
[
(((((use_arg_then2 ("perm_rot", [perm_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_rot *)
let nth_rot = Sections.section_proof ["x0";"s";"k";"i"]
`k <= sizel s /\ i < sizel s
==> nth x0 (rot k s) i = nth x0 s ((k + i) MOD sizel s)`
[
(BETA_TAC THEN (move ["ineqs"]));
((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`i:num < _`))) (disch_eq_tac "i_lt" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("nth_drop", [nth_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`i - (sizel s - k) = (k + i) - sizel s`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) ((((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((THENL_FIRST) (((use_arg_then2 ("nth_take", [nth_take]))(thm_tac (new_rewrite [] [])))) ((((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k + i = 1 * sizel s + ((k + i) - sizel s)`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [2] []))))))) ((((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((use_arg_then2 ("MOD_MULT_ADD", [MOD_MULT_ADD]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((use_arg_then2 ("ineqs", [])) (disch_tac [])) THEN (clear_assumption "ineqs") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma rot_to_index_explicit *)
let rot_to_index_explicit = Sections.section_proof ["s";"x"]
`MEM x s
==> rot (indexl x s) s = x :: dropl 1 (rot (indexl x s) s)`
[
(BETA_TAC THEN (move ["mem_x"]));
((fun arg_tac -> arg_tac (Arg_term (`0 < sizel s /\ indexl x s < sizel s`))) (term_tac (have_gen_tac [](move ["ineqs"]))));
(((((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_x", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_predT", [has_predT]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predT", [predT]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] []))))) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
(((((fun arg_tac -> (use_arg_then2 ("cons_head_drop1", [cons_head_drop1])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [1] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN ((congr_tac (`_1 :: _2`)) THEN ((TRY done_tac))));
(((((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_rot", [nth_rot]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltnW", [ltnW]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot_to_index *)
let rot_to_index = Sections.section_proof ["s";"x"]
`MEM x s ==> ?t. rot (indexl x s) s = x :: t`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("rot_to_index_explicit", [rot_to_index_explicit])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((fun arg_tac -> arg_tac (Arg_term (`dropl 1 (rot (indexl x s) s)`))) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma shift_right *)
let shift_right = Sections.section_proof ["h";"t"]
`rotr 1 [] = [] /\
rotr 1 (h :: t) = belast (last h t) (h :: t)`
[
(((((use_arg_then2 ("rotr_nil", [rotr_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [1] [])))) THEN (((use_arg_then2 ("rotr1_rcons", [rotr1_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_shift_left *)
let nth_shift_left = Sections.section_proof ["x0";"s";"i"]
`i < sizel s ==>
nth x0 (rot 1 s) i = if (i = sizel s - 1) then nth x0 s 0 else nth x0 s (i + 1)`
[
(BETA_TAC THEN (move ["i_lt"]));
((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn_neqAle", [ltn_neqAle]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`i = sizel s - 1`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((THENL_FIRST) ((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_take", [nth_take]))(thm_tac (new_rewrite [] []))))) ((((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((congr_tac (`nth x0 s _`)) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`i <= sizel s - 1`))) (term_tac (have_gen_tac []((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac))))) ((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("nth_drop", [nth_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addnC", [addnC]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN ((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma nth_shift_right *)
let nth_shift_right = Sections.section_proof ["x0";"s";"i"]
`i < sizel s ==>
nth x0 (rotr 1 s) i = if (i = 0) then nth x0 s (sizel s - 1) else nth x0 s (i - 1)`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["Ih"]) THEN (move ["i_lt"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("shift_right", [shift_right]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`i = 0`))) (disch_eq_tac "i_eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("i_eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("last_nth", [last_nth])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((fun arg_tac -> (use_arg_then2 ("num_CASES", [num_CASES])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN ((TRY done_tac)) THEN (case THEN (move ["m"])) THEN (move ["i_eq"]));
((((use_arg_then2 ("i_eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("EQ_SYM_EQ", [EQ_SYM_EQ]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_rcons", [nth_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_belast", [size_belast]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("i_eq", [])) (disch_tac [])) THEN (clear_assumption "i_eq") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma rot_rot_eq_rot *)
let rot_rot_eq_rot = Sections.section_proof ["s";"m";"n"]
`?k. rot m (rot n s) = rot k s`
[
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`m <= sizel s`))) (disch_eq_tac "m_le" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
(((use_arg_then2 ("n", [])) (term_tac exists_tac)) THEN ((((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("m_le", [])) (disch_tac [])) THEN (clear_assumption "m_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`n <= sizel s`))) (disch_eq_tac "n_le" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
(((use_arg_then2 ("m", [])) (term_tac exists_tac)) THEN ((((fun arg_tac -> (use_arg_then2 ("rot_oversize", [rot_oversize])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("rot_add_mod", [rot_add_mod]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`if _ then _1 else _2`))) (term_tac (set_tac "k")));
(((use_arg_then2 ("k", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma index_rot *)
let index_rot = Sections.section_proof ["s";"n";"x"]
`uniq s /\ n < sizel s /\ MEM x s ==>
indexl x (rot n s) = if n <= indexl x s then (indexl x s - n)
else (indexl x s + sizel s - n)`
[
(BETA_TAC THEN (case THEN (move ["uniq_s"])) THEN (case THEN (move ["n_lt"])) THEN (move ["mem_x"]));
((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_cat", [index_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_drop_uniq", [index_drop_uniq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("index_take", [index_take]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`indexl x s`))) (term_tac (set_tac "i")));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`i < sizel s`))) (term_tac (have_gen_tac [](move ["i_lt"])))) ((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN BETA_TAC) THEN ((((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("i_def", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma rotr1_eq_cons *)
let rotr1_eq_cons = Sections.section_proof ["h";"t"]
`rotr 1 (h :: t) = last h t :: belast h t`
[
(((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [1] [])))) THEN (((use_arg_then2 ("rotr1_rcons", [rotr1_rcons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section MoreRot *)
let rot_nil = Sections.finalize_theorem rot_nil;;
let rotr_nil = Sections.finalize_theorem rotr_nil;;
let perm_eq_rot = Sections.finalize_theorem perm_eq_rot;;
let nth_rot = Sections.finalize_theorem nth_rot;;
let rot_to_index_explicit = Sections.finalize_theorem rot_to_index_explicit;;
let rot_to_index = Sections.finalize_theorem rot_to_index;;
let shift_right = Sections.finalize_theorem shift_right;;
let nth_shift_left = Sections.finalize_theorem nth_shift_left;;
let nth_shift_right = Sections.finalize_theorem nth_shift_right;;
let rot_rot_eq_rot = Sections.finalize_theorem rot_rot_eq_rot;;
let index_rot = Sections.finalize_theorem index_rot;;
let rotr1_eq_cons = Sections.finalize_theorem rotr1_eq_cons;;
Sections.end_section "MoreRot";;
(* Section NextPrev *)
Sections.begin_section "NextPrev";;
(* Lemma next_el_outside *)
let next_el_outside = Sections.section_proof ["s";"x"]
`~(MEM x s) ==> next_el s x = x`
[
((repeat_tactic 1 9 (((use_arg_then2 ("index_eq_size", [index_eq_size]))(thm_tac (new_rewrite [] []))))) THEN (move ["i_eq"]));
((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_eq", []))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `!n. ~(SUC n = SUC n - 1)`)))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
(((repeat_tactic 1 9 (((use_arg_then2 ("nth_default", [nth_default]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma prev_el_outside *)
let prev_el_outside = Sections.section_proof ["s";"x"]
`~(MEM x s) ==> prev_el s x = x`
[
(((((use_arg_then2 ("prev_el", [prev_el]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_el_rot *)
let next_el_rot = Sections.section_proof ["x";"s"]
`MEM x s ==>
next_el s x = headl x (rot (indexl x s + 1) s)`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["x_list"]))]) ((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x _ = _2`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subn_gt0", [subn_gt0]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("LT_LE", [LT_LE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn1", [addn1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("x_list", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
(((((use_arg_then2 ("nth_drop", [nth_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_rot *)
let prev_el_rot = Sections.section_proof ["x";"s"]
`MEM x s ==>
prev_el s x = headl x (rotr 1 (rot (indexl x s) s))`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["x_list"]))]) ((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("prev_el", [prev_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("x_list", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x _ = _2`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot0", [rot0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [2] [])))) THEN (((use_arg_then2 ("rotr1_rcons", [rotr1_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_add_mod", [rot_add_mod]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("leq_pred", [leq_pred]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_eqVlt", [leq_eqVlt]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x (CONS h t) = 1`))) (disch_eq_tac "eq2" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("eq2", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth0", [nth0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn1", [addn1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`SUC (sizel t) < sizel t + indexl x (CONS h t)`))) (term_tac (have_gen_tac [](move ["neq"])))) ((((use_arg_then2 ("eq2", [])) (disch_tac [])) THEN (clear_assumption "eq2") THEN ((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((use_arg_then2 ("leqNgt", [leqNgt]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("neq", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subn_gt0", [subn_gt0]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`(sizel t + indexl x (CONS h t)) - SUC (sizel t) < sizel (CONS h t)`))) (term_tac (have_gen_tac []((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)))));
((((use_arg_then2 ("eq2", [])) (disch_tac [])) THEN (clear_assumption "eq2") THEN ((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("x_list", [])) (disch_tac [])) THEN (clear_assumption "x_list") THEN BETA_TAC) THEN ((((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("nth_drop", [nth_drop]))(thm_tac (new_rewrite [] [])))) THEN ((congr_tac (`nth x _1 _2`)) THEN ((TRY done_tac))));
((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma next_el_alt *)
let next_el_alt = Sections.section_proof ["x0";"x";"s"]
`MEM x s ==> next_el s x = nth x0 (rot 1 s) (indexl x s)`
[
((BETA_TAC THEN (move ["xs"])) THEN ((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("nth_shift_left", [nth_shift_left])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((((fun arg_tac -> arg_tac (Arg_term (`indexl x s = _`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN ((use_arg_then2 ("set_nth_default", [set_nth_default])) (thm_tac apply_tac)) THEN (((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma prev_el_alt *)
let prev_el_alt = Sections.section_proof ["x0";"x";"s"]
`MEM x s ==> prev_el s x = nth x0 (rotr 1 s) (indexl x s)`
[
((BETA_TAC THEN (move ["xs"])) THEN ((((use_arg_then2 ("prev_el", [prev_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("xs", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((fun arg_tac -> (use_arg_then2 ("nth_shift_right", [nth_shift_right])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("nth_last", [nth_last]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((((fun arg_tac -> arg_tac (Arg_term (`indexl x s = _`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) THEN ((use_arg_then2 ("set_nth_default", [set_nth_default])) (thm_tac apply_tac)) THEN (((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma mem_next_el *)
let mem_next_el = Sections.section_proof ["x";"s"]
`MEM x s ==> MEM (next_el s x) s`
[
((BETA_TAC THEN (move ["xs"])) THEN ((((fun arg_tac -> (use_arg_then2 ("next_el_alt", [next_el_alt])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`HD s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("mem_rot", [mem_rot])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_prev_el *)
let mem_prev_el = Sections.section_proof ["x";"s"]
`MEM x s ==> MEM (prev_el s x) s`
[
((BETA_TAC THEN (move ["xs"])) THEN ((((fun arg_tac -> (use_arg_then2 ("prev_el_alt", [prev_el_alt])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`HD s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("mem_rotr", [mem_rotr])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_rotr", [size_rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_next_id *)
let prev_next_id = Sections.section_proof ["x";"s"]
`uniq s ==> prev_el s (next_el s x) = x`
[
((THENL_LAST) (((fun arg_tac -> arg_tac (Arg_term (`MEM x s`))) (disch_eq_tac "xs" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("next_el_outside", [next_el_outside]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("prev_el_outside", [prev_el_outside]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(BETA_TAC THEN (move ["uniq_s"]));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`0 < sizel s`))) (term_tac (have_gen_tac [](move ["size_gt"])))) (((((use_arg_then2 ("has_predT", [has_predT]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predT", [predT]))(thm_tac (new_rewrite [] []))))) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac)));
((((fun arg_tac -> (use_arg_then2 ("prev_el_alt", [prev_el_alt])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`HD s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mem_next_el", [mem_next_el]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("next_el_alt", [next_el_alt])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`HD s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((use_arg_then2 ("nth_shift_left", [nth_shift_left]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x s = sizel s - 1`))) (disch_eq_tac "eq1" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("nth_shift_right", [nth_shift_right]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("eq1", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("nth_shift_right", [nth_shift_right]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("uniq_s", []))(thm_tac (new_rewrite [] [])))))) THEN (TRY (((((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN ((use_arg_then2 ("eq1", [])) (disch_tac [])) THEN (clear_assumption "eq1") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (arith_tac)))));
(((((use_arg_then2 ("addn1", [addn1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_prev_id *)
let next_prev_id = Sections.section_proof ["x";"s"]
`uniq s ==> next_el s (prev_el s x) = x`
[
((THENL_LAST) (((fun arg_tac -> arg_tac (Arg_term (`MEM x s`))) (disch_eq_tac "xs" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("prev_el_outside", [prev_el_outside]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("next_el_outside", [next_el_outside]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((BETA_TAC THEN (move ["uniq_s"])) THEN ((fun arg_tac -> arg_tac (Arg_term (`HD s`))) (term_tac (set_tac "x0"))));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`0 < sizel s`))) (term_tac (have_gen_tac [](move ["size_gt"])))) (((((use_arg_then2 ("has_predT", [has_predT]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predT", [predT]))(thm_tac (new_rewrite [] []))))) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac)));
((((fun arg_tac -> (use_arg_then2 ("next_el_alt", [next_el_alt])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mem_prev_el", [mem_prev_el]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("prev_el_alt", [prev_el_alt])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((use_arg_then2 ("nth_shift_right", [nth_shift_right]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x s = 0`))) (disch_eq_tac "eq1" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
(((((use_arg_then2 ("nth_shift_left", [nth_shift_left]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("uniq_s", []))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (TRY (((((use_arg_then2 ("size_gt", [])) (disch_tac [])) THEN (clear_assumption "size_gt") THEN BETA_TAC) THEN (arith_tac)))));
(((((use_arg_then2 ("eq1", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("nth_shift_left", [nth_shift_left]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("uniq_s", []))(thm_tac (new_rewrite [] [])))))) THEN (TRY (((((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN ((use_arg_then2 ("eq1", [])) (disch_tac [])) THEN (clear_assumption "eq1") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (arith_tac)))));
((fun arg_tac -> arg_tac (Arg_term (`~(indexl x s - 1 = sizel s - 1)`))) (term_tac (have_gen_tac []((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)))));
((((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN ((use_arg_then2 ("eq1", [])) (disch_tac [])) THEN (clear_assumption "eq1") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
(((((use_arg_then2 ("subnK", [subnK]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("eq1", [])) (disch_tac [])) THEN (clear_assumption "eq1") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma next_el_mod *)
let next_el_mod = Sections.section_proof ["x0";"s";"x"]
`MEM x s
==> next_el s x = nth x0 s ((indexl x s + 1) MOD sizel s)`
[
((BETA_TAC THEN (move ["xs"])) THEN ((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (term_tac (set_tac "n")));
((fun arg_tac -> arg_tac (Arg_term (`1 <= n /\ ~(n = 0)`))) (term_tac (have_gen_tac [](case THEN ((move ["ge1"]) THEN (move ["neq0"]))))));
((((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN BETA_TAC) THEN (((((use_arg_then2 ("MEM_EXISTS_EL", [MEM_EXISTS_EL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size", [size]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["i"]))) THEN (arith_tac) THEN (done_tac));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x s = _`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subnK", [subnK]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("muln1", [muln1])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("MOD_MULT", [MOD_MULT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
(((use_arg_then2 ("set_nth_default", [set_nth_default])) (thm_tac apply_tac)) THEN ((((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt0n", [lt0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`indexl x s + 1 < n`))) (term_tac (have_gen_tac [](move ["lt"]))));
((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN ((use_arg_then2 ("xs", [])) (disch_tac [])) THEN (clear_assumption "xs") THEN BETA_TAC) THEN ((((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] []))))) THEN (arith_tac) THEN (done_tac));
(((((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN ((use_arg_then2 ("set_nth_default", [set_nth_default])) (thm_tac apply_tac)) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma next_el_power *)
let next_el_power = Sections.section_proof ["x0";"s";"x";"i"]
`uniq s /\ MEM x s
==> (next_el s POWER i) x = nth x0 s ((indexl x s + i) MOD (sizel s))`
[
(BETA_TAC THEN (case THEN ((move ["uniq_s"]) THEN (move ["mem_x"]))));
((fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (term_tac (set_tac "n")));
((fun arg_tac -> arg_tac (Arg_term (`indexl x s`))) (term_tac (set_tac "k")));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k < n:num`))) (term_tac (have_gen_tac [](move ["k_lt"])))) (((((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("n_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN elim) [ALL_TAC; ((move ["i"]) THEN (move ["Ih"]))]);
(((((use_arg_then2 ("Hypermap.POWER_0", [Hypermap.POWER_0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("I_THM", [I_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`~(n = 0)`))) (term_tac (have_gen_tac [](move ["neq0"]))));
((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN ((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac)) THEN (((((use_arg_then2 ("n_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_eq0", [size_eq0]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
((((use_arg_then2 ("Hypermap.COM_POWER", [Hypermap.COM_POWER]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("o_THM", [o_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Ih", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("next_el_mod", [next_el_mod]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("DIVISION", [DIVISION]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("index_uniq", [index_uniq])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("DIVISION", [DIVISION]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac)));
(congr_tac (`nth x0 s _`));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k + SUC i = (k + i) + 1`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) ((arith_tac) THEN (done_tac)));
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("MOD_ADD_MOD", [MOD_ADD_MOD])) (fun fst_arg -> (use_arg_then2 ("neq0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`k + i:num`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [])))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`n = 1`))) (disch_eq_tac "eq1" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) (((((use_arg_then2 ("eq1", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("MOD_1", [MOD_1]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac)));
(((((fun arg_tac -> (use_arg_then2 ("MOD_LT", [MOD_LT])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("neq0", [])) (disch_tac [])) THEN (clear_assumption "neq0") THEN ((use_arg_then2 ("eq1", [])) (disch_tac [])) THEN (clear_assumption "eq1") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma next_el_orbit *)
let next_el_orbit = Sections.section_proof ["s";"x"]
`uniq s /\ MEM x s
==> orbit_map (next_el s) x = set_of_list s`
[
(BETA_TAC THEN (case THEN ((move ["uniq_s"]) THEN (move ["mem_x"]))));
((fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (term_tac (set_tac "n")));
((fun arg_tac -> arg_tac (Arg_term (`HD s`))) (term_tac (set_tac "x0")));
((fun arg_tac -> arg_tac (Arg_term (`~(n = 0)`))) (term_tac (have_gen_tac [](move ["neq0"]))));
((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN ((use_arg_then2 ("contraL", [contraL])) (disch_tac [])) THEN (clear_assumption "contraL") THEN (DISCH_THEN apply_tac)) THEN (((((use_arg_then2 ("n_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_eq0", [size_eq0]))(thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
(((((use_arg_then2 ("Hypermap.orbit_map", [Hypermap.orbit_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("EXTENSION", [EXTENSION]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_ELIM_THM", [IN_ELIM_THM]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["d"]));
((THENL) (split_tac) [((case THEN (move ["i"])) THEN (case THEN (move ["i_ge0"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))); (move ["mem_d"])]);
(((((fun arg_tac -> (use_arg_then2 ("next_el_power", [next_el_power])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mem_nth", [mem_nth]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("DIVISION", [DIVISION]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`indexl x s`))) (term_tac (set_tac "k")));
((fun arg_tac -> arg_tac (Arg_term (`indexl d s`))) (term_tac (set_tac "i")));
((fun arg_tac -> arg_tac (Arg_term (`k < n /\ i < n:num`))) (term_tac (have_gen_tac [](case THEN ((move ["k_lt"]) THEN (move ["i_lt"]))))));
(((((use_arg_then2 ("n_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("k_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("i_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`n - k + i:num`))) (term_tac exists_tac));
((((use_arg_then2 ("GE", [GE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("LE_0", [LE_0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> (use_arg_then2 ("next_el_power", [next_el_power])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("k_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("n_def", []))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`k + n - k + i = n + i:num`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) ((((use_arg_then2 ("k_lt", [])) (disch_tac [])) THEN (clear_assumption "k_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(((((fun arg_tac -> (use_arg_then2 ("mul1n", [mul1n])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("MOD_MULT_ADD", [MOD_MULT_ADD]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MOD_LT", [MOD_LT]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("i_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_el_rot_eq *)
let next_el_rot_eq = Sections.section_proof ["s";"n"]
`uniq s ==> next_el (rot n s) = next_el s`
[
((BETA_TAC THEN (move ["uniq_s"])) THEN ((((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] [])))) THEN (move ["x"])));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`n < sizel s`))) (disch_eq_tac "n_lt" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
(((((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("NOT_LT", [NOT_LT]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`MEM x s`))) (disch_eq_tac "mem_x" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
(((repeat_tactic 1 9 (((use_arg_then2 ("next_el_outside", [next_el_outside]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mem_rot", [mem_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`MEM x (rot n s)`))) (term_tac (have_gen_tac [](move ["mem_rot"])))) ((((use_arg_then2 ("mem_rot", [mem_rot]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((repeat_tactic 1 9 (((use_arg_then2 ("next_el_rot", [next_el_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth0", [nth0]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("index_rot", [index_rot]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`indexl x s`))) (term_tac (set_tac "i")));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`i < sizel s`))) (term_tac (have_gen_tac [](move ["i_lt"])))) ((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN BETA_TAC) THEN (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`0 < sizel s`))) (term_tac (have_gen_tac [](move ["size_gt0"]))));
(((THENL) (((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`i + 1 <= sizel s /\ n <= sizel s /\ i - n + 1 <= sizel s /\ ~(0 = sizel s)`))) (term_tac (have_gen_tac [](move ["ineqs"]))));
((((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN ((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac));
(((fun arg_tac -> arg_tac (Arg_term (`n:num <= _`))) (disch_eq_tac "n_le" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac));
((repeat_tactic 1 9 (((use_arg_then2 ("nth_rot", [nth_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("DIVISION", [DIVISION]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac)));
((((fun arg_tac -> (use_arg_then2 ("MOD_LT", [MOD_LT])) (fun fst_arg -> (use_arg_then2 ("n_lt", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("MOD_ADD_MOD", [MOD_ADD_MOD]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
(((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`n + i - n + 1 = i + 1`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) ((((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac))) THEN (done_tac));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`(i + sizel s - n) + 1 <= sizel s`))) (term_tac (have_gen_tac [](move ["ineq2"])))) ((((use_arg_then2 ("i_lt", [])) (disch_tac [])) THEN (clear_assumption "i_lt") THEN ((use_arg_then2 ("n_le", [])) (disch_tac [])) THEN (clear_assumption "n_le") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((repeat_tactic 1 9 (((use_arg_then2 ("nth_rot", [nth_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("DIVISION", [DIVISION]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] []))))));
((((fun arg_tac -> (use_arg_then2 ("MOD_LT", [MOD_LT])) (fun fst_arg -> (use_arg_then2 ("n_lt", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("MOD_ADD_MOD", [MOD_ADD_MOD]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`n + (i + sizel s - n) + 1 = 1 * sizel s + (i + 1)`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) ((((use_arg_then2 ("n_lt", [])) (disch_tac [])) THEN (clear_assumption "n_lt") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
((((use_arg_then2 ("MOD_MULT_ADD", [MOD_MULT_ADD]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma next_el_inj *)
let next_el_inj = Sections.section_proof ["s";"x";"y"]
`uniq s ==> (next_el s x = next_el s y <=> x = y)`
[
((BETA_TAC THEN (move ["uniq_s"])) THEN ((THENL) (split_tac) [ALL_TAC; ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))]));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`MEM x s`))) (disch_eq_tac "mem_x" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
(((((use_arg_then2 ("next_el_outside", [next_el_outside]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (move ["x_eq"]));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`~MEM y s`))) (term_tac (have_gen_tac [](move ["mem_y"]))))) ((((use_arg_then2 ("x_eq", [])) (disch_tac [])) THEN (clear_assumption "x_eq") THEN BETA_TAC) THEN (((use_arg_then2 ("next_el_outside", [next_el_outside]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("mem_x", [])) (disch_tac [])) THEN (clear_assumption "mem_x") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("mem_next_el", [mem_next_el])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (((use_arg_then2 ("x_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_ROT (-1)) (((fun arg_tac -> arg_tac (Arg_term (`MEM y s`))) (disch_eq_tac "mem_y" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)));
((((fun arg_tac -> (use_arg_then2 ("next_el_outside", [next_el_outside])) (fun fst_arg -> (use_arg_then2 ("mem_y", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (move ["y_eq"]));
((((fun arg_tac -> (use_arg_then2 ("mem_next_el", [mem_next_el])) (fun fst_arg -> (use_arg_then2 ("mem_x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("y_eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_y", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((DISCH_THEN (fun snd_th -> (fun arg_tac -> (use_arg_then2 ("congr1", [congr1])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`prev_el s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (repeat_tactic 1 9 (((use_arg_then2 ("prev_next_id", [prev_next_id]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_rot_eq *)
let prev_el_rot_eq = Sections.section_proof ["s";"n"]
`uniq s ==> prev_el (rot n s) = prev_el s`
[
((((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] [])))) THEN (move ["uniq_s"]) THEN (move ["x"]));
(((((fun arg_tac -> (use_arg_then2 ("next_el_inj", [next_el_inj])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("next_el_rot_eq", [next_el_rot_eq])) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("next_prev_id", [next_prev_id]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("rot_uniq", [rot_uniq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_inj *)
let prev_el_inj = Sections.section_proof ["s";"x";"y"]
`uniq s ==> (prev_el s x = prev_el s y <=> x = y)`
[
((BETA_TAC THEN (move ["uniq_s"])) THEN (((THENL) (split_tac) [ALL_TAC; (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) THEN ((TRY done_tac))));
(((((fun arg_tac -> (use_arg_then2 ("next_el_inj", [next_el_inj])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("next_prev_id", [next_prev_id]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma next_el_permutes *)
let next_el_permutes = Sections.section_proof ["s"]
`uniq s ==> (next_el s) permutes (set_of_list s)`
[
((((((use_arg_then2 ("permutes", [permutes]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IN_SET_OF_LIST", [IN_SET_OF_LIST]))(thm_tac (new_rewrite [] []))))) THEN (move ["uniq_s"])) THEN ((THENL) (split_tac) [(move ["x"]); (move ["y"])]));
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("next_el_outside", [next_el_outside])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
((((use_arg_then2 ("EXISTS_UNIQUE_ALT", [EXISTS_UNIQUE_ALT]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> arg_tac (Arg_term (`prev_el s y`))) (term_tac exists_tac)) THEN (move ["z"])));
(((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("prev_el_inj", [prev_el_inj])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`next_el s z`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("prev_next_id", [prev_next_id]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("eq_sym", [eq_sym])) (fun fst_arg -> (use_arg_then2 ("z", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma inverse_next_el *)
let inverse_next_el = Sections.section_proof ["s"]
`uniq s ==> inverse (next_el s) = prev_el s`
[
((((use_arg_then2 ("FUN_EQ_THM", [FUN_EQ_THM]))(thm_tac (new_rewrite [] [])))) THEN (move ["uniq_s"]) THEN (move ["x"]));
(((((fun arg_tac -> (use_arg_then2 ("PERMUTES_INVERSE_EQ", [PERMUTES_INVERSE_EQ])) (fun fst_arg -> (fun arg_tac -> (use_arg_then2 ("next_el_permutes", [next_el_permutes])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("next_prev_id", [next_prev_id]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_permutes *)
let prev_el_permutes = Sections.section_proof ["s"]
`uniq s ==> (prev_el s) permutes (set_of_list s)`
[
((BETA_TAC THEN (move ["uniq_s"])) THEN ((((use_arg_then2 ("inverse_next_el", [inverse_next_el]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("PERMUTES_INVERSE", [PERMUTES_INVERSE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("next_el_permutes", [next_el_permutes]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma inverse_prev_el *)
let inverse_prev_el = Sections.section_proof ["s"]
`uniq s ==> inverse (prev_el s) = next_el s`
[
((BETA_TAC THEN (move ["uniq_s"])) THEN ((((use_arg_then2 ("inverse_next_el", [inverse_next_el]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((fun arg_tac -> (fun arg_tac -> arg_tac (Arg_theorem (GEN_ALL PERMUTES_INVERSE_INVERSE))) (fun fst_arg -> (fun arg_tac -> (use_arg_then2 ("next_el_permutes", [next_el_permutes])) (fun fst_arg -> (use_arg_then2 ("uniq_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma next_el_rotr_eq *)
let next_el_rotr_eq = Sections.section_proof ["s";"n"]
`uniq s ==> next_el (rotr n s) = next_el s`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("next_el_rot_eq", [next_el_rot_eq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (move ["eq"])) THEN ((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_rotr_eq *)
let prev_el_rotr_eq = Sections.section_proof ["s";"n"]
`uniq s ==> prev_el (rotr n s) = prev_el s`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("prev_el_rot_eq", [prev_el_rot_eq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (move ["eq"])) THEN ((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_el_hd_cons2 *)
let next_el_hd_cons2 = Sections.section_proof ["h1";"h2";"t"]
`next_el (h1 :: (h2 :: t)) h1 = h2`
[
((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Seq.index_head", [Seq.index_head]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))));
((THENL_FIRST) (((fun arg_tac -> arg_tac (Arg_term (`0 = _`))) (disch_eq_tac "eq" [])) THEN case THEN (simp_tac) THEN (process_fst_eq_tac)) ((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN (arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("addn1", [addn1]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma next_el_hd_cons *)
let next_el_hd_cons = Sections.section_proof ["h";"t"]
`0 < sizel t ==> next_el (h :: t) h = HD t`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN case) [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("next_el_hd_cons2", [next_el_hd_cons2]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_el_hd_belast *)
let next_el_hd_belast = Sections.section_proof ["h";"t"]
`1 < sizel t ==> next_el (belast h t) h = HD t`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN case) [ALL_TAC; ((move ["h2"]) THEN (move ["t"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN case) [ALL_TAC; ((move ["h3"]) THEN (move ["t"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("belast", [belast]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("next_el_hd_cons2", [next_el_hd_cons2]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma next_el_last *)
let next_el_last = Sections.section_proof ["x0";"s"]
`0 < sizel s /\ uniq s ==> next_el s (last x0 s) = HD s`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (case THEN (move ["_"])) THEN (move ["uniq_s"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("next_el", [next_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_last", [index_last]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("succnK", [succnK]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("head", [head]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma prev_el_hd *)
let prev_el_hd = Sections.section_proof ["x0";"s"]
`0 < sizel s ==> prev_el s (HD s) = last x0 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("HD", [HD]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("prev_el", [prev_el]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("MEM", [MEM]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("Seq.index_head", [Seq.index_head]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (repeat_tactic 1 9 (((use_arg_then2 ("last", [last]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Finalization of the section NextPrev *)
let next_el_outside = Sections.finalize_theorem next_el_outside;;
let prev_el_outside = Sections.finalize_theorem prev_el_outside;;
let next_el_rot = Sections.finalize_theorem next_el_rot;;
let prev_el_rot = Sections.finalize_theorem prev_el_rot;;
let next_el_alt = Sections.finalize_theorem next_el_alt;;
let prev_el_alt = Sections.finalize_theorem prev_el_alt;;
let mem_next_el = Sections.finalize_theorem mem_next_el;;
let mem_prev_el = Sections.finalize_theorem mem_prev_el;;
let prev_next_id = Sections.finalize_theorem prev_next_id;;
let next_prev_id = Sections.finalize_theorem next_prev_id;;
let next_el_mod = Sections.finalize_theorem next_el_mod;;
let next_el_power = Sections.finalize_theorem next_el_power;;
let next_el_orbit = Sections.finalize_theorem next_el_orbit;;
let next_el_rot_eq = Sections.finalize_theorem next_el_rot_eq;;
let next_el_inj = Sections.finalize_theorem next_el_inj;;
let prev_el_rot_eq = Sections.finalize_theorem prev_el_rot_eq;;
let prev_el_inj = Sections.finalize_theorem prev_el_inj;;
let next_el_permutes = Sections.finalize_theorem next_el_permutes;;
let inverse_next_el = Sections.finalize_theorem inverse_next_el;;
let prev_el_permutes = Sections.finalize_theorem prev_el_permutes;;
let inverse_prev_el = Sections.finalize_theorem inverse_prev_el;;
let next_el_rotr_eq = Sections.finalize_theorem next_el_rotr_eq;;
let prev_el_rotr_eq = Sections.finalize_theorem prev_el_rotr_eq;;
let next_el_hd_cons2 = Sections.finalize_theorem next_el_hd_cons2;;
let next_el_hd_cons = Sections.finalize_theorem next_el_hd_cons;;
let next_el_hd_belast = Sections.finalize_theorem next_el_hd_belast;;
let next_el_last = Sections.finalize_theorem next_el_last;;
let prev_el_hd = Sections.finalize_theorem prev_el_hd;;
Sections.end_section "NextPrev";;
(* Close the module *)
end;;