needs "Examples/ssrnat-compiled.hl";;
(* Module Seq*)
module Seq = struct
open Ssrfun;;
open Ssrbool;;
open Ssrnat;;
prioritize_num();;
(* Section Sequences *)
Sections.begin_section "Sequences";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_var (mk_var ("x0", (`:A`))));;
(Sections.add_section_type (mk_var ("x", (`:A`))); Sections.add_section_type (mk_var ("y", (`:A`))); Sections.add_section_type (mk_var ("z", (`:A`))));;
(Sections.add_section_type (mk_var ("m", (`:num`))); Sections.add_section_type (mk_var ("n", (`:num`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(* Lemma size0nil *)
let size0nil = Sections.section_proof ["s"]
`sizel s = 0 ==> s = []`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN (BETA_TAC THEN ((TRY done_tac))) THEN ((((use_arg_then2 ("size", [size]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma nilP *)
let nilP = Sections.section_proof ["s"]
`s = [] <=> nilp s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((((use_arg_then2 ("nilp", [nilp]))(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 done_tac)) THEN (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("NOT_SUC", [NOT_SUC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_behead *)
let size_behead = Sections.section_proof ["s"]
`sizel (behead s) = (sizel s) - 1`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN case) [ALL_TAC; ((move ["h"]) THEN (move ["t"]))]) THEN ((((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size", [size]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("SUC_SUB1", [SUC_SUB1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_nil *)
let size_nil = Sections.section_proof []
`sizel ([]:(A)list) = 0`
[
(((((use_arg_then2 ("size", [size]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_cons *)
let size_cons = Sections.section_proof ["h";"t"]
`sizel (CONS (h:A) t) = SUC (sizel t)`
[
(((((use_arg_then2 ("size", [size]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("LENGTH", [LENGTH]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_ncons *)
let size_ncons = Sections.section_proof ["n";"x";"s"]
`sizel (ncons n x s) = n + sizel s`
[
((((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ncons", [ncons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((repeat_tactic 0 10 (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (move ["n"]) THEN (move ["IH"])));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IH", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addSn", [addSn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_nseq *)
let size_nseq = Sections.section_proof ["n";"x"]
`sizel (nseq n (x:A)) = n`
[
(((((use_arg_then2 ("nseq", [nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_ncons", [size_ncons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
parse_as_infix ("::", (12, "right"));;
override_interface ("::", `CONS`);;
make_overloadable "++" `:A -> A -> A`;;
let cat = define `!(x:A) t s2. cat [] s2 = s2 /\ cat (CONS x t) s2 = x :: cat t s2`;;
overload_interface ("++", `cat`);;
(* Lemma cat0s *)
let cat0s = Sections.section_proof ["s"]
`[] ++ (s:(A)list) = s`
[
((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma cat1s *)
let cat1s = Sections.section_proof ["x";"s"]
`[x:A] ++ s = x :: s`
[
((repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma cat_cons *)
let cat_cons = Sections.section_proof ["x";"s1";"s2"]
`(x :: s1) ++ s2 = x :: s1 ++ s2`
[
((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma cat_nseq *)
let cat_nseq = Sections.section_proof ["n";"x";"s"]
`nseq n (x:A) ++ s = ncons n x s`
[
((((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) THEN (((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (move ["n"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma cats0 *)
let cats0 = Sections.section_proof ["s"]
`s ++ [] = (s:(A)list)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN (((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma catA *)
let catA = Sections.section_proof ["s1";"s2";"s3"]
`s1 ++ s2 ++ s3 = (s1 ++ s2) ++ s3:(A)list`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]))]) THEN (((repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_cat *)
let size_cat = Sections.section_proof ["s1";"s2"]
`sizel (s1 ++ s2) = sizel s1 + sizel (s2:(A)list)`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]))]) THEN (((repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("addSn", [addSn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rcons_cons *)
let rcons_cons = Sections.section_proof ["x";"s";"z"]
`rcons (x :: s) z = x:A :: rcons s z`
[
((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma cats1 *)
let cats1 = Sections.section_proof ["s";"z"]
`s ++ [z:A] = rcons s z`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN (((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma lastI *)
let lastI = Sections.section_proof ["x";"s"]
`(x:A :: s) = rcons (belast x s) (last x 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma last_cons *)
let last_cons = Sections.section_proof ["x";"y";"s"]
`last x (y:A :: s) = last y s`
[
((((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma size_rcons *)
let size_rcons = Sections.section_proof ["s";"x"]
`sizel (rcons s (x:A)) = SUC (sizel s)`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((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 ("addnS", [addnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_belast *)
let size_belast = Sections.section_proof ["x";"s"]
`sizel (belast (x:A) s) = sizel 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma last_cat *)
let last_cat = Sections.section_proof ["x";"s1";"s2"]
`last (x:A) (s1 ++ s2) = last (last x s1) s2`
[
(((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma last_rcons *)
let last_rcons = Sections.section_proof ["x";"s";"z"]
`last x (rcons s z) = z:A`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("last_cat", [last_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma belast_cat *)
let belast_cat = Sections.section_proof ["x";"s1";"s2"]
`belast x (s1 ++ s2) = belast x s1 ++ belast (last (x:A) s1) s2`
[
(((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma belast_rcons *)
let belast_rcons = Sections.section_proof ["x";"s";"z"]
`belast x (rcons s z) = x:A :: s`
[
(((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("belast_cat", [belast_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma cat_rcons *)
let cat_rcons = Sections.section_proof ["x";"s1";"s2"]
`rcons s1 x ++ s2 = s1 ++ (x:A :: s2)`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catA", [catA]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma rcons_cat *)
let rcons_cat = Sections.section_proof ["x";"s1";"s2"]
`rcons (s1 ++ s2) x = s1 ++ rcons s2 (x:A)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma last_ind *)
let last_ind = Sections.section_proof ["P"]
`P [] ==> (!s (x : A). P s ==> P (rcons s x)) ==> (!s. P s)`
[
(BETA_TAC THEN (move ["Hnil"]) THEN (move ["Hlast"]) THEN (move ["s"]));
(((fun arg_tac -> (use_arg_then2 ("cat0s", [cat0s])) (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 [] [])))));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("Hnil", [])) (disch_tac [])) THEN (clear_assumption "Hnil") THEN ((fun arg_tac -> arg_tac (Arg_term (`[]`))) (disch_tac [])) THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s2"]) THEN (move ["IHs"]))]) ((((use_arg_then2 ("cats0", [cats0]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
(((((use_arg_then2 ("cat_rcons", [cat_rcons]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (move ["s1"]) THEN (move ["Ps1"])) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("Hlast", [])) (disch_tac [])) THEN (clear_assumption "Hlast") THEN (exact_tac)) THEN (done_tac));
];;
let nth = define `!(x0:A) h t n. nth x0 [] n = x0 /\ nth x0 (h :: t) 0 = h /\ nth x0 (h :: t) (SUC n) = nth x0 t n`;;
(* Lemma nth0 *)
let nth0 = Sections.section_proof ["s"]
`nth x0 s 0 = headl x0 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["h"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("head", [head]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_default *)
let nth_default = Sections.section_proof ["s";"n"]
`sizel s <= n ==> nth x0 s n = x0`
[
((((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) case [ALL_TAC; (move ["n"])])) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma nth_nil *)
let nth_nil = Sections.section_proof ["n"]
`nth x0 [] n = x0`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma last_nth *)
let last_nth = Sections.section_proof ["x";"s"]
`last x s = nth x0 (x :: s) (sizel s)`
[
((THENL_FIRST) (((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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) (done_tac));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma nth_last *)
let nth_last = Sections.section_proof ["s"]
`nth x0 s (sizel s - 1) = last x0 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["t"]) THEN (move ["h"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("succnK", [succnK]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last_nth", [last_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_behead *)
let nth_behead = Sections.section_proof ["s";"n"]
`nth x0 (behead s) n = nth x0 s (SUC 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 ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_cat *)
let nth_cat = Sections.section_proof ["s1";"s2";"n"]
`nth x0 (s1 ++ s2) n = if n < sizel s1 then nth x0 s1 n else nth x0 s2 (n - sizel s1)`
[
((THENL) (((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) [(arith_tac); (arith_tac); BETA_TAC]);
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_rcons *)
let nth_rcons = Sections.section_proof ["s";"x";"n"]
`nth x0 (rcons s x) n =
if n < sizel s then nth x0 s n else if n = sizel s then x else x0`
[
((THENL_FIRST) (((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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0Sn", [ltn0Sn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac))) ((arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_ncons *)
let nth_ncons = Sections.section_proof ["m";"x";"s";"n"]
`nth x0 (ncons m x s) n = if n < m then x else nth x0 s (n - m)`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN elim) [ALL_TAC; ((move ["m"]) THEN (move ["IHm"]))]) THEN ((THENL) case [ALL_TAC; (move ["n"])])) THEN ((((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (TRY ((arith_tac))));
(((((use_arg_then2 ("IHm", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_nseq *)
let nth_nseq = Sections.section_proof ["m";"x";"n"]
`nth x0 (nseq m x) n = (if n < m then x else x0)`
[
((((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN elim) [ALL_TAC; ((move ["m"]) THEN (move ["IHm"]))]) THEN ((THENL) case [ALL_TAC; (move ["n"])])) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (TRY ((arith_tac))));
(((((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 ("IHm", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_from_nth *)
let eq_from_nth = Sections.section_proof ["s1";"s2"]
`sizel s1 = sizel s2 ==> (!i. i < sizel s1 ==> nth x0 s1 i = nth x0 s2 i) ==>
s1 = 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 ["x1"]) THEN (move ["s1"]) THEN (move ["IHs1"]))]) THEN ((THENL) case [ALL_TAC; ((move ["x2"]) THEN (move ["s2"]))])) THEN ((((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("NOT_SUC", [NOT_SUC]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (move ["eq_sz"]) THEN (move ["eq_s12"]));
((((fun arg_tac -> (use_arg_then2 ("eq_s12", [])) (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 ("ltn0Sn", [ltn0Sn]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 2 0 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (move ["_"])) THEN (((((fun arg_tac -> (use_arg_then2 ("IHs1", [])) (fun fst_arg -> (use_arg_then2 ("s2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("eq_sz", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (move ["i"])));
((((fun arg_tac -> (use_arg_then2 ("eq_s12", [])) (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 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 2 0 (((use_arg_then2 ("nth", [nth]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma size_set_nth *)
let size_set_nth = Sections.section_proof ["s";"n";"y"]
`sizel (set_nth x0 s n y) = maxn (SUC n) (sizel 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("set_nth", [set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))));
(((((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("maxn", [maxn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (arith_tac) THEN (done_tac));
(((((use_arg_then2 ("size_ncons", [size_ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ONE", [ONE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("addn1", [addn1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("maxn", [maxn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (arith_tac) THEN (done_tac));
((((use_arg_then2 ("add_sub_maxn", [add_sub_maxn]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (arith_tac) THEN (done_tac));
(((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add1n", [add1n]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("addn_maxr", [addn_maxr]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("add1n", [add1n]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma set_nth_nil *)
let set_nth_nil = Sections.section_proof ["n";"y"]
`set_nth x0 [] n y = ncons n x0 [y]`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("set_nth", [set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma ltS0 *)
let ltS0 = Sections.section_proof ["n"]
`SUC n < 0 <=> F`
[
((arith_tac) THEN (done_tac));
];;
(* Lemma eqS0 *)
let eqS0 = Sections.section_proof ["n"]
`SUC n = 0 <=> F`
[
((arith_tac) THEN (done_tac));
];;
(* Lemma eq0S *)
let eq0S = Sections.section_proof ["n"]
`0 = SUC n <=> F`
[
((arith_tac) THEN (done_tac));
];;
(* Lemma gtS0 *)
let gtS0 = Sections.section_proof ["n"]
`0 < SUC n`
[
((arith_tac) THEN (done_tac));
];;
(* Lemma ltSS *)
let ltSS = Sections.section_proof ["m";"n"]
`SUC m < SUC n <=> m < n`
[
((arith_tac) THEN (done_tac));
];;
(* Lemma nth_set_nth *)
let nth_set_nth = Sections.section_proof ["s";"n";"y";"i"]
`nth x0 (set_nth x0 s n y) i = if i = n then y else nth x0 s i`
[
((THENL_ROT (-1)) (((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["m"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("set_nth", [set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth_nil", [nth_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth_ncons", [nth_ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("eq0S", [eq0S]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))))));
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))));
((THENL_LAST) ((THENL) (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltngtP", [ltngtP])) (fun fst_arg -> (use_arg_then2 ("m", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [(move ["lt_mn"]); ((THENL) case [(move ["lt_nm"]); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))])]) (((((use_arg_then2 ("subnn", [subnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac)));
(((((use_arg_then2 ("lt_mn", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `m < n ==> (m = n <=> F)`)))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_LAST) ((((use_arg_then2 ("nth_default", [nth_default]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("if_same", [if_same]))(thm_tac (new_rewrite [] [])))))) ((((fun arg_tac -> arg_tac (Arg_theorem (ARITH_RULE `n < m ==> (m = n <=> F)`)))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
(((((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 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subn_gt0", [subn_gt0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma set_set_nth *)
let set_set_nth = Sections.section_proof ["s";"n1";"y1";"n2";"y2"]
`set_nth x0 (set_nth x0 s n1 y1) n2 y2 =
if n1 = n2 then set_nth x0 s n2 y2 else set_nth x0 (set_nth x0 s n2 y2) n1 y1`
[
((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`n1 = n2:num`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)); (move ["ne_n12"])]);
((THENL_FIRST) ((((fun arg_tac -> arg_tac (Arg_theorem (REWRITE_RULE[IMP_IMP] eq_from_nth))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (split_tac)) (((repeat_tactic 1 9 (((use_arg_then2 ("size_set_nth", [size_set_nth]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("maxnA", [maxnA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("maxnn", [maxnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((BETA_TAC THEN (move ["i"]) THEN (move ["_"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("nth_set_nth", [nth_set_nth]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (done_tac));
((THENL_FIRST) ((((fun arg_tac -> arg_tac (Arg_theorem (REWRITE_RULE[IMP_IMP] eq_from_nth))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (split_tac)) (((((use_arg_then2 ("ne_n12", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_set_nth", [size_set_nth]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("maxnCA", [maxnCA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((BETA_TAC THEN (move ["i"]) THEN (move ["_"])) THEN (((simp_tac THEN TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth_set_nth", [nth_set_nth]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN ((((use_arg_then2 ("ne_n12", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`i = n2:num`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [(((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))); (move ["ne_i2"])]) THEN (simp_tac));
(((((use_arg_then2 ("nth_set_nth", [nth_set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ne_n12", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nth_set_nth", [nth_set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
(((((use_arg_then2 ("ne_i2", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth_set_nth", [nth_set_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ne_i2", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Section SeqFind *)
Sections.begin_section "SeqFind";;
(Sections.add_section_var (mk_var ("a", (`:A -> bool`))));;
let find = define `!a (x:A) s'. find a [] = 0 /\
find a (x :: s') = if a x then 0 else SUC(find a s')`;;
let filter = define `!a (x:A) s'. filter a [] = [] /\
filter a (x :: s') = if a x then x :: filter a s' else filter a s'`;;
let has = define `!a (x:A) s'. has a [] = F /\
has a (x :: s') = (a x \/ has a s')`;;
let all = define `!a (x:A) s'. all a [] = T /\
all a (x :: s') = (a x /\ all a s')`;;
(* Lemma find_nil *)
let find_nil = Sections.section_proof []
`find a [] = 0`
[
((((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma find_cons *)
let find_cons = Sections.section_proof ["x";"t"]
`find a (x::t) = if a x then 0 else SUC (find a t)`
[
((((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma filter_nil *)
let filter_nil = Sections.section_proof []
`filter a [] = []`
[
((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma filter_cons *)
let filter_cons = Sections.section_proof ["x";"t"]
`filter a (x::t) = if a x then x :: filter a t else filter a t`
[
((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma count_nil *)
let count_nil = Sections.section_proof []
`count a [] = 0`
[
((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma count_cons *)
let count_cons = Sections.section_proof ["x";"t"]
`count a (x::t) = (if a x then 1 else 0) + count a t`
[
((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma has_nil *)
let has_nil = Sections.section_proof []
`has a [] = F`
[
((repeat_tactic 1 9 (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma has_cons *)
let has_cons = Sections.section_proof ["x";"t"]
`has a (x::t) <=> a x \/ has a t`
[
((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma all_nil *)
let all_nil = Sections.section_proof []
`all a [] = T`
[
((repeat_tactic 1 9 (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma all_cons *)
let all_cons = Sections.section_proof ["x";"t"]
`all a (x::t) <=> a x /\ all a t`
[
((((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma count_filter *)
let count_filter = Sections.section_proof ["s"]
`count a s = sizel (filter a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN (((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))));
(((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)); (move ["nax"])]) THEN ((((use_arg_then2 ("add1n", [add1n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("nax", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma has_count *)
let has_count = Sections.section_proof ["s"]
`has a s = (0 < count a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN (((((use_arg_then2 ("has", [has]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count", [count]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> arg_tac (Arg_term (`a x`))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (arith_tac) THEN (done_tac));
];;
(* Lemma count_size *)
let count_size = Sections.section_proof ["s"]
`count a s <= sizel s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN ((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> arg_tac (Arg_term (`a x`))) (disch_tac [])) THEN case THEN (simp_tac)) THEN ((((fun arg_tac ->(use_arg_then2 ("add1n", [add1n]))(fun tmp_arg1 -> (use_arg_then2 ("add0n", [add0n]))(fun tmp_arg2 -> arg_tac (Arg_theorem (CONJ (get_arg_thm tmp_arg1) (get_arg_thm tmp_arg2))))))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(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 ("leqW", [leqW])) (disch_tac [])) THEN (clear_assumption "leqW") THEN (exact_tac)));
];;
(* Lemma all_count *)
let all_count = Sections.section_proof ["s"]
`all a s = (count a s = sizel s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]))]) THEN ((((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((THENL_FIRST) ((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"]) THEN (move ["_"])) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) ((arith_tac) THEN (done_tac)));
(((((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqn_leq", [eqn_leq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_size", [count_size]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma filter_all *)
let filter_all = Sections.section_proof ["s"]
`all a (filter a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma all_filterP *)
let all_filterP = Sections.section_proof ["s"]
`(filter a s = s) <=> (all a s)`
[
((THENL_FIRST) ((THENL) (EQ_TAC) [(((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))); ALL_TAC]) ((((use_arg_then2 ("filter_all", [filter_all]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN ALL_TAC THEN (case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (move ["Hs"]))) THEN (simp_tac)));
((((fun arg_tac -> (use_arg_then2 ("IHs", [])) (fun fst_arg -> (use_arg_then2 ("Hs", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma filter_id *)
let filter_id = Sections.section_proof ["s"]
`filter a (filter a s) = filter a s`
[
(((((use_arg_then2 ("all_filterP", [all_filterP]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("filter_all", [filter_all]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_find *)
let has_find = Sections.section_proof ["s"]
`has a s <=> (find a s < sizel s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((simp_tac THEN TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("gtS0", [gtS0]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma find_size *)
let find_size = Sections.section_proof ["s"]
`find a s <= sizel s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma find_cat *)
let find_cat = Sections.section_proof ["s1";"s2"]
`find a (s1 ++ s2) = if has a s1 then find a s1 else sizel s1 + find a s2`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"]));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("fun_if", [fun_if]))(thm_tac (new_rewrite [] [(`SUC _1`)])))) THEN (((use_arg_then2 ("addSn", [addSn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_nil *)
let has_nil = Sections.section_proof []
`has a [] = F`
[
((repeat_tactic 1 9 (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma has_seq1 *)
let has_seq1 = Sections.section_proof ["x"]
`has a [x] = a x`
[
((repeat_tactic 1 9 (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma has_seqb *)
let has_seqb = Sections.section_proof ["b";"x"]
`has a (nseq (if b then 1 else 0) x) <=> (b /\ a x)`
[
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case THEN (simp_tac)) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ONE", [ONE]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("has_nil", [has_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("has_seq1", [has_seq1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma all_nil *)
let all_nil = Sections.section_proof []
`all a [] = T`
[
((repeat_tactic 1 9 (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma all_seq1 *)
let all_seq1 = Sections.section_proof ["x"]
`all a [x] = a x`
[
((repeat_tactic 1 9 (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_find *)
let nth_find = Sections.section_proof ["s"]
`has a s ==> a (nth x0 s (find a s))`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma before_find *)
let before_find = Sections.section_proof ["s";"i"]
`i < find a s ==> (a (nth x0 s i) <=> F)`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((THENL_FIRST) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ax"])) ((((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
(((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ax", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltSS", [ltSS]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma filter_cat *)
let filter_cat = Sections.section_proof ["s1";"s2"]
`filter a (s1 ++ s2) = filter a s1 ++ filter a s2`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["Ihs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma filter_rcons *)
let filter_rcons = Sections.section_proof ["s";"x"]
`filter a (rcons s x) = if a x then rcons (filter a s) x else filter a s`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("filter_cat", [filter_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN (((use_arg_then2 ("cats0", [cats0]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma count_cat *)
let count_cat = Sections.section_proof ["s1";"s2"]
`count a (s1 ++ s2) = count a s1 + count a s2`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("filter_cat", [filter_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_cat *)
let has_cat = Sections.section_proof ["s1";"s2"]
`has a (s1 ++ s2) = (has a s1 \/ has a s2)`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbA", [orbA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_rcons *)
let has_rcons = Sections.section_proof ["s";"x"]
`has a (rcons s x) = (a x \/ has a s)`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_cat", [has_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_seq1", [has_seq1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbC", [orbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_cat *)
let all_cat = Sections.section_proof ["s1";"s2"]
`all a (s1 ++ s2) = (all a s1 /\ all a s2)`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbA", [andbA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_rcons *)
let all_rcons = Sections.section_proof ["s";"x"]
`all a (rcons s x) = (a x /\ all a s)`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("all_cat", [all_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("all_seq1", [all_seq1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section SeqFind *)
let find_nil = Sections.finalize_theorem find_nil;;
let find_cons = Sections.finalize_theorem find_cons;;
let filter_nil = Sections.finalize_theorem filter_nil;;
let filter_cons = Sections.finalize_theorem filter_cons;;
let count_nil = Sections.finalize_theorem count_nil;;
let count_cons = Sections.finalize_theorem count_cons;;
let has_nil = Sections.finalize_theorem has_nil;;
let has_cons = Sections.finalize_theorem has_cons;;
let all_nil = Sections.finalize_theorem all_nil;;
let all_cons = Sections.finalize_theorem all_cons;;
let count_filter = Sections.finalize_theorem count_filter;;
let has_count = Sections.finalize_theorem has_count;;
let count_size = Sections.finalize_theorem count_size;;
let all_count = Sections.finalize_theorem all_count;;
let filter_all = Sections.finalize_theorem filter_all;;
let all_filterP = Sections.finalize_theorem all_filterP;;
let filter_id = Sections.finalize_theorem filter_id;;
let has_find = Sections.finalize_theorem has_find;;
let find_size = Sections.finalize_theorem find_size;;
let find_cat = Sections.finalize_theorem find_cat;;
let has_nil = Sections.finalize_theorem has_nil;;
let has_seq1 = Sections.finalize_theorem has_seq1;;
let has_seqb = Sections.finalize_theorem has_seqb;;
let all_nil = Sections.finalize_theorem all_nil;;
let all_seq1 = Sections.finalize_theorem all_seq1;;
let nth_find = Sections.finalize_theorem nth_find;;
let before_find = Sections.finalize_theorem before_find;;
let filter_cat = Sections.finalize_theorem filter_cat;;
let filter_rcons = Sections.finalize_theorem filter_rcons;;
let count_cat = Sections.finalize_theorem count_cat;;
let has_cat = Sections.finalize_theorem has_cat;;
let has_rcons = Sections.finalize_theorem has_rcons;;
let all_cat = Sections.finalize_theorem all_cat;;
let all_rcons = Sections.finalize_theorem all_rcons;;
Sections.end_section "SeqFind";;
(* Lemma eq_find *)
let eq_find = Sections.section_proof ["a1";"a2"]
`(!x:A. a1 x = a2 x) ==> (!s. find a1 s = find a2 s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_filter *)
let eq_filter = Sections.section_proof ["a1";"a2"]
`(!x:A. a1 x = a2 x) ==> (!s. filter a1 s = filter a2 s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_count *)
let eq_count = Sections.section_proof ["a1";"a2"]
`(!x:A. a1 x = a2 x) ==> (!s. count a1 s = count a2 s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_has *)
let eq_has = Sections.section_proof ["a1";"a2"]
`(!x. a1 x = a2 x) ==> (!s. has a1 s = has a2 s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_all *)
let eq_all = Sections.section_proof ["a1";"a2"]
`(!x. a1 x = a2 x) ==> (!s. all a1 s = all a2 s)`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma filter_pred0 *)
let filter_pred0 = Sections.section_proof ["s"]
`filter pred0 s = []`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("pred0", [pred0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("pred0", [pred0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma filter_predT *)
let filter_predT = Sections.section_proof ["s"]
`filter predT s = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("predT", [predT]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [2] []))))) THEN (((use_arg_then2 ("predT", [predT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma filter_predI *)
let filter_predI = Sections.section_proof ["a1";"a2";"s"]
`filter (predI a1 a2) s = filter a1 (filter a2 s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("predI", [predI]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((THENL_LAST) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a2:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) (((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predI", [predI]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a1:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["a1x"])) THEN (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))));
(((((use_arg_then2 ("a1x", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("IHs", []))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("predI", [predI]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
(((((use_arg_then2 ("a1x", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("IHs", []))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("predI", [predI]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma count_pred0 *)
let count_pred0 = Sections.section_proof ["s"]
`count pred0 s = 0`
[
(((((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("filter_pred0", [filter_pred0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_predT *)
let count_predT = Sections.section_proof ["s"]
`count predT s = sizel s`
[
(((((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("filter_predT", [filter_predT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_predUI *)
let count_predUI = Sections.section_proof ["a1";"a2";"s"]
`count (predU a1 a2) s + count (predI a1 a2) s = count a1 s + count a2 (s:(A)list)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("predI", [predI]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("predU", [predU]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a1:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["a1x"])) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a2:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["a2x"])) THEN ((((use_arg_then2 ("predI", [predI]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predU", [predU]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN BETA_TAC) THEN (arith_tac));
];;
(* Lemma count_predC *)
let count_predC = Sections.section_proof ["a";"s"]
`count a s + count (predC a) s = sizel (s:(A)list)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
((((use_arg_then2 ("addnCA", [addnCA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addnA", [addnA]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ax"])) THEN (arith_tac));
];;
(* Lemma has_pred0 *)
let has_pred0 = Sections.section_proof ["s"]
`has pred0 s = F`
[
(((((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_pred0", [count_pred0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_predT *)
let has_predT = Sections.section_proof ["s"]
`has predT s = (0 < sizel s)`
[
(((((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_predT", [count_predT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_predC *)
let has_predC = Sections.section_proof ["a";"s"]
`has (predC a) s = ~ all a s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_predU *)
let has_predU = Sections.section_proof ["a1";"a2";"s"]
`has (predU a1 a2) s <=> (has a1 s \/ has a2 s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predU", [predU]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (repeat_tactic 1 9 (((use_arg_then2 ("orbA", [orbA]))(gsym_then (thm_tac (new_rewrite [] [])))))));
((((use_arg_then2 ("orbCA", [orbCA]))(thm_tac (new_rewrite [] [(`has a1 s \/ _ \/ _1`)])))) THEN (done_tac));
];;
(* Lemma all_pred0 *)
let all_pred0 = Sections.section_proof ["s"]
`all pred0 s = (sizel s = 0)`
[
(((((use_arg_then2 ("all_count", [all_count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_pred0", [count_pred0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`0 = _`)]))))) THEN (done_tac));
];;
(* Lemma all_predT *)
let all_predT = Sections.section_proof ["s"]
`all predT s`
[
(((((use_arg_then2 ("all_count", [all_count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_predT", [count_predT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_predC *)
let all_predC = Sections.section_proof ["a";"s"]
`all (predC a) s = ~ has a s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_or", [negb_or]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma can_inj *)
let can_inj = Sections.section_proof ["f";"g"]
`(!x. g (f x) = x) ==> (!x y. f x = f y ==> x = y)`
[
(BETA_TAC THEN (move ["h"]) THEN (move ["x"]) THEN (move ["y"]) THEN (move ["f_eq"]));
(((((fun arg_tac -> (use_arg_then2 ("h", [])) (fun fst_arg -> (use_arg_then2 ("x", [])) (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 ("h", [])) (fun fst_arg -> (use_arg_then2 ("y", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("f_eq", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_predI *)
let all_predI = Sections.section_proof ["a1";"a2";"s"]
`all (predI a1 a2) s <=> all a1 s /\ all a2 s`
[
((((fun arg_tac -> (use_arg_then2 ("can_inj", [can_inj])) (fun fst_arg -> (use_arg_then2 ("negbK", [negbK])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN ((((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("has_predC", [has_predC]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("has_predU", [has_predU]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("predU", [predU]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predI", [predI]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
let drop = define `!n x s. dropl (SUC n) (x :: s) = dropl n s /\
dropl n [] = [] /\ dropl 0 s = s`;;
(* Lemma eq_ext *)
let eq_ext = Sections.section_proof ["f";"g"]
`(!x. f x = g x) <=> f = g`
[
((THENL_FIRST) ((split_tac) THEN (move ["h"])) ((MATCH_MP_TAC EQ_EXT) THEN (done_tac)));
((((use_arg_then2 ("h", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma drop_nil *)
let drop_nil = Sections.section_proof ["n"]
`dropl n [] = []`
[
((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma drop0 *)
let drop0 = Sections.section_proof []
`dropl 0 = I`
[
(((((use_arg_then2 ("eq_ext", [eq_ext]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("I_THM", [I_THM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma drop_cons *)
let drop_cons = Sections.section_proof ["n";"x";"s"]
`dropl (SUC n) (x :: s) = dropl n s`
[
((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma drop_behead *)
let drop_behead = Sections.section_proof []
`dropl n0 = iter n0 behead`
[
((THENL_FIRST) (((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((((use_arg_then2 ("eq_ext", [eq_ext]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) ((((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac)));
(((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("iterSr", [iterSr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHn", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma drop0 *)
let drop0 = Sections.section_proof ["s"]
`dropl 0 s = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma drop1 *)
let drop1 = Sections.section_proof ["s"]
`dropl 1 s = behead s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("ONE", [ONE]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("drop0", [drop0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma drop_oversize *)
let drop_oversize = Sections.section_proof ["n";"s"]
`sizel s <= n ==> dropl n s = []`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHn", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma drop_size *)
let drop_size = Sections.section_proof ["s"]
`dropl (sizel s) s = []`
[
(((((use_arg_then2 ("drop_oversize", [drop_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_drop *)
let size_drop = Sections.section_proof ["s"]
`sizel (dropl n0 s) = sizel s - n0`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma drop_cat *)
let drop_cat = Sections.section_proof ["s1";"s2"]
`dropl n0 (s1 ++ s2) =
if n0 < sizel s1 then dropl n0 s1 ++ s2 else dropl (n0 - sizel s1) s2`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("if_same", [if_same]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma drop_size_cat *)
let drop_size_cat = Sections.section_proof ["n";"s1";"s2"]
`sizel s1 = n ==> dropl n (s1 ++ s2) = s2`
[
((BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop0", [drop0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop_cons", [drop_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nconsK *)
let nconsK = Sections.section_proof ["n";"x";"s"]
`dropl n (ncons n x s) = s`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
let take = define `!x s n. take (SUC n) (x :: s) = x :: take n s /\
take 0 s = [] /\ take n [] = []`;;
(* Lemma take0 *)
let take0 = Sections.section_proof ["s"]
`take 0 s = []`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma take_oversize *)
let take_oversize = Sections.section_proof ["n";"s"]
`sizel s <= n ==> take n s = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (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 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["Hsn"])) THEN (((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma take_size *)
let take_size = Sections.section_proof ["s"]
`take (sizel s) s = s`
[
(((((use_arg_then2 ("take_oversize", [take_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma take_cons *)
let take_cons = Sections.section_proof ["x";"s"]
`take (SUC n0) (x :: s) = x :: (take n0 s)`
[
((((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma drop_rcons *)
let drop_rcons = Sections.section_proof ["s"]
`n0 <= sizel s ==>
!x. dropl n0 (rcons s x) = rcons (dropl n0 s) x`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop_cons", [drop_cons]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma congr1 *)
let congr1 = Sections.section_proof ["f";"x";"y"]
`x = y ==> f x = f y`
[
((BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma cat_take_drop *)
let cat_take_drop = Sections.section_proof ["s"]
`take n0 s ++ dropl n0 s = s`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma size_takel *)
let size_takel = Sections.section_proof ["s"]
`n0 <= sizel s ==> sizel (take n0 s) = n0`
[
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("subnKC", [subnKC])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN ((((fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (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 [2] []))))) THEN (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("addIn", [addIn])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma size_take *)
let size_take = Sections.section_proof ["s"]
`sizel (take n0 s) = if n0 < sizel s then n0 else sizel s`
[
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("leqP", [leqP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel (s:(A)list)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN ((THENL) case [(move ["le_sn"]); (move ["lt_ns"])]));
(((((use_arg_then2 ("take_oversize", [take_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("le_sn", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
(((((use_arg_then2 ("lt_ns", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("size_takel", [size_takel]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltnW", [ltnW]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma take_cat *)
let take_cat = Sections.section_proof ["s1";"s2"]
`take n0 (s1 ++ s2) =
if n0 < sizel s1 then take n0 s1 else s1 ++ take (n0 - sizel s1) s2`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("subn0", [subn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("fun_if", [fun_if]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma take_size_cat *)
let take_size_cat = Sections.section_proof ["n";"s1";"s2"]
`sizel s1 = n ==> take n (s1 ++ s2) = s1`
[
((BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma takel_cat *)
let takel_cat = Sections.section_proof ["s1"]
`n0 <= sizel (s1:(A)list) ==> (!s2. take n0 (s1 ++ s2) = take n0 s1)`
[
(BETA_TAC THEN (move ["Hn0"]) THEN (move ["s2"]));
((((use_arg_then2 ("take_cat", [take_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn_neqAle", [ltn_neqAle]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hn0", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`n0 = sizel (s1:(A)list)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["eq"]));
(((((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take0", [take0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats0", [cats0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take_size", [take_size]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_drop *)
let nth_drop = Sections.section_proof ["s";"i"]
`nth x0 (dropl n0 s) i = nth x0 s (n0 + i)`
[
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltnP", [ltnP])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel (s:(A)list)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN ((THENL) case [(move ["lt_n0_s"]); (move ["le_s_n0"])]));
((((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(gsym_then (thm_tac (new_rewrite [2] [(`s`)]))))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt_n0_s", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("addKn", [addKn]))(thm_tac (new_rewrite [] [])))));
(((((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_addr", [leq_addr]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((repeat_tactic 1 9 (((use_arg_then2 ("nth_default", [nth_default]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
((((use_arg_then2 ("le_s_n0", [])) (disch_tac [])) THEN (clear_assumption "le_s_n0") THEN BETA_TAC) THEN (((((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leqE", [leqE]))(thm_tac (new_rewrite [] [])))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("sub0n", [sub0n]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("leq_trans", [leq_trans])) (fun fst_arg -> (use_arg_then2 ("le_s_n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("leq_addr", [leq_addr]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma nth_take *)
let nth_take = Sections.section_proof ["i"]
`i < n0 ==> !s. nth x0 (take n0 s) i = nth x0 s i`
[
((BETA_TAC THEN (move ["lt_i_n0"]) THEN (move ["s"])) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`n0 < sizel (s:(A)list)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (move ["lt_n0_s"])));
(((((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(gsym_then (thm_tac (new_rewrite [2] [(`s`)]))))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt_n0_s", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("lt_i_n0", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("cats0", [cats0]))(gsym_then (thm_tac (new_rewrite [1] [(`s`)]))))) THEN (((use_arg_then2 ("take_cat", [take_cat]))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("lt_n0_s", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cats0", [cats0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma drop_nth *)
let drop_nth = Sections.section_proof ["n";"s"]
`n < sizel s ==> dropl n s = nth x0 s n :: dropl (SUC n) 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma take_nth *)
let take_nth = Sections.section_proof ["n";"s"]
`n < sizel s ==> take (SUC n) s = rcons (take n s) (nth x0 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot0 *)
let rot0 = Sections.section_proof ["s"]
`rot 0 s = s`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop0", [drop0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take0", [take0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats0", [cats0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_rot *)
let size_rot = Sections.section_proof ["s"]
`sizel (rot n0 s) = sizel s`
[
(((((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(gsym_then (thm_tac (new_rewrite [2] [(`s`)]))))) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("addnC", [addnC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot_oversize *)
let rot_oversize = Sections.section_proof ["n";"s"]
`sizel s <= n ==> rot n s = s`
[
((BETA_TAC THEN (move ["le_s_n"])) THEN ((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take_oversize", [take_oversize]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("drop_oversize", [drop_oversize]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma rot_size *)
let rot_size = Sections.section_proof ["s"]
`rot (sizel s) s = s`
[
((((use_arg_then2 ("rot_oversize", [rot_oversize])) (disch_tac [])) THEN (clear_assumption "rot_oversize") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma has_rot *)
let has_rot = Sections.section_proof ["s";"a"]
`has a (rot n0 s) = has a s`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_cat", [has_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbC", [orbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_cat", [has_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot_size_cat *)
let rot_size_cat = Sections.section_proof ["s1";"s2"]
`rot (sizel s1) (s1 ++ s2) = s2 ++ s1`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take_size_cat", [take_size_cat]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("drop_size_cat", [drop_size_cat]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rotK *)
let rotK = Sections.section_proof ["s"]
`rotr n0 (rot n0 s) = s`
[
((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [(`rot n0 _`)])))));
(((((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot_inj *)
let rot_inj = Sections.section_proof ["s1";"s2"]
`rot n0 (s1:(A)list) = rot n0 s2 ==> s1 = s2`
[
((((fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("can_inj", [can_inj])) (fun fst_arg -> (use_arg_then2 ("rotK", [rotK])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("s1", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("s2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma rot1_cons *)
let rot1_cons = Sections.section_proof ["x";"s"]
`rot 1 (x :: s) = rcons s x`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop_cons", [drop_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take", [take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("take0", [take0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop0", [drop0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Finalization of the section Sequences *)
let size0nil = Sections.finalize_theorem size0nil;;
let nilP = Sections.finalize_theorem nilP;;
let size_behead = Sections.finalize_theorem size_behead;;
let size_nil = Sections.finalize_theorem size_nil;;
let size_cons = Sections.finalize_theorem size_cons;;
let size_ncons = Sections.finalize_theorem size_ncons;;
let size_nseq = Sections.finalize_theorem size_nseq;;
let cat0s = Sections.finalize_theorem cat0s;;
let cat1s = Sections.finalize_theorem cat1s;;
let cat_cons = Sections.finalize_theorem cat_cons;;
let cat_nseq = Sections.finalize_theorem cat_nseq;;
let cats0 = Sections.finalize_theorem cats0;;
let catA = Sections.finalize_theorem catA;;
let size_cat = Sections.finalize_theorem size_cat;;
let rcons_cons = Sections.finalize_theorem rcons_cons;;
let cats1 = Sections.finalize_theorem cats1;;
let lastI = Sections.finalize_theorem lastI;;
let last_cons = Sections.finalize_theorem last_cons;;
let size_rcons = Sections.finalize_theorem size_rcons;;
let size_belast = Sections.finalize_theorem size_belast;;
let last_cat = Sections.finalize_theorem last_cat;;
let last_rcons = Sections.finalize_theorem last_rcons;;
let belast_cat = Sections.finalize_theorem belast_cat;;
let belast_rcons = Sections.finalize_theorem belast_rcons;;
let cat_rcons = Sections.finalize_theorem cat_rcons;;
let rcons_cat = Sections.finalize_theorem rcons_cat;;
let last_ind = Sections.finalize_theorem last_ind;;
let nth0 = Sections.finalize_theorem nth0;;
let nth_default = Sections.finalize_theorem nth_default;;
let nth_nil = Sections.finalize_theorem nth_nil;;
let last_nth = Sections.finalize_theorem last_nth;;
let nth_last = Sections.finalize_theorem nth_last;;
let nth_behead = Sections.finalize_theorem nth_behead;;
let nth_cat = Sections.finalize_theorem nth_cat;;
let nth_rcons = Sections.finalize_theorem nth_rcons;;
let nth_ncons = Sections.finalize_theorem nth_ncons;;
let nth_nseq = Sections.finalize_theorem nth_nseq;;
let eq_from_nth = Sections.finalize_theorem eq_from_nth;;
let size_set_nth = Sections.finalize_theorem size_set_nth;;
let set_nth_nil = Sections.finalize_theorem set_nth_nil;;
let ltS0 = Sections.finalize_theorem ltS0;;
let eqS0 = Sections.finalize_theorem eqS0;;
let eq0S = Sections.finalize_theorem eq0S;;
let gtS0 = Sections.finalize_theorem gtS0;;
let ltSS = Sections.finalize_theorem ltSS;;
let nth_set_nth = Sections.finalize_theorem nth_set_nth;;
let set_set_nth = Sections.finalize_theorem set_set_nth;;
let find_nil = Sections.finalize_theorem find_nil;;
let find_cons = Sections.finalize_theorem find_cons;;
let filter_nil = Sections.finalize_theorem filter_nil;;
let filter_cons = Sections.finalize_theorem filter_cons;;
let count_nil = Sections.finalize_theorem count_nil;;
let count_cons = Sections.finalize_theorem count_cons;;
let has_nil = Sections.finalize_theorem has_nil;;
let has_cons = Sections.finalize_theorem has_cons;;
let all_nil = Sections.finalize_theorem all_nil;;
let all_cons = Sections.finalize_theorem all_cons;;
let count_filter = Sections.finalize_theorem count_filter;;
let has_count = Sections.finalize_theorem has_count;;
let count_size = Sections.finalize_theorem count_size;;
let all_count = Sections.finalize_theorem all_count;;
let filter_all = Sections.finalize_theorem filter_all;;
let all_filterP = Sections.finalize_theorem all_filterP;;
let filter_id = Sections.finalize_theorem filter_id;;
let has_find = Sections.finalize_theorem has_find;;
let find_size = Sections.finalize_theorem find_size;;
let find_cat = Sections.finalize_theorem find_cat;;
let has_nil = Sections.finalize_theorem has_nil;;
let has_seq1 = Sections.finalize_theorem has_seq1;;
let has_seqb = Sections.finalize_theorem has_seqb;;
let all_nil = Sections.finalize_theorem all_nil;;
let all_seq1 = Sections.finalize_theorem all_seq1;;
let nth_find = Sections.finalize_theorem nth_find;;
let before_find = Sections.finalize_theorem before_find;;
let filter_cat = Sections.finalize_theorem filter_cat;;
let filter_rcons = Sections.finalize_theorem filter_rcons;;
let count_cat = Sections.finalize_theorem count_cat;;
let has_cat = Sections.finalize_theorem has_cat;;
let has_rcons = Sections.finalize_theorem has_rcons;;
let all_cat = Sections.finalize_theorem all_cat;;
let all_rcons = Sections.finalize_theorem all_rcons;;
let eq_find = Sections.finalize_theorem eq_find;;
let eq_filter = Sections.finalize_theorem eq_filter;;
let eq_count = Sections.finalize_theorem eq_count;;
let eq_has = Sections.finalize_theorem eq_has;;
let eq_all = Sections.finalize_theorem eq_all;;
let filter_pred0 = Sections.finalize_theorem filter_pred0;;
let filter_predT = Sections.finalize_theorem filter_predT;;
let filter_predI = Sections.finalize_theorem filter_predI;;
let count_pred0 = Sections.finalize_theorem count_pred0;;
let count_predT = Sections.finalize_theorem count_predT;;
let count_predUI = Sections.finalize_theorem count_predUI;;
let count_predC = Sections.finalize_theorem count_predC;;
let has_pred0 = Sections.finalize_theorem has_pred0;;
let has_predT = Sections.finalize_theorem has_predT;;
let has_predC = Sections.finalize_theorem has_predC;;
let has_predU = Sections.finalize_theorem has_predU;;
let all_pred0 = Sections.finalize_theorem all_pred0;;
let all_predT = Sections.finalize_theorem all_predT;;
let all_predC = Sections.finalize_theorem all_predC;;
let can_inj = Sections.finalize_theorem can_inj;;
let all_predI = Sections.finalize_theorem all_predI;;
let eq_ext = Sections.finalize_theorem eq_ext;;
let drop_nil = Sections.finalize_theorem drop_nil;;
let drop0 = Sections.finalize_theorem drop0;;
let drop_cons = Sections.finalize_theorem drop_cons;;
let drop_behead = Sections.finalize_theorem drop_behead;;
let drop0 = Sections.finalize_theorem drop0;;
let drop1 = Sections.finalize_theorem drop1;;
let drop_oversize = Sections.finalize_theorem drop_oversize;;
let drop_size = Sections.finalize_theorem drop_size;;
let size_drop = Sections.finalize_theorem size_drop;;
let drop_cat = Sections.finalize_theorem drop_cat;;
let drop_size_cat = Sections.finalize_theorem drop_size_cat;;
let nconsK = Sections.finalize_theorem nconsK;;
let take0 = Sections.finalize_theorem take0;;
let take_oversize = Sections.finalize_theorem take_oversize;;
let take_size = Sections.finalize_theorem take_size;;
let take_cons = Sections.finalize_theorem take_cons;;
let drop_rcons = Sections.finalize_theorem drop_rcons;;
let congr1 = Sections.finalize_theorem congr1;;
let cat_take_drop = Sections.finalize_theorem cat_take_drop;;
let size_takel = Sections.finalize_theorem size_takel;;
let size_take = Sections.finalize_theorem size_take;;
let take_cat = Sections.finalize_theorem take_cat;;
let take_size_cat = Sections.finalize_theorem take_size_cat;;
let takel_cat = Sections.finalize_theorem takel_cat;;
let nth_drop = Sections.finalize_theorem nth_drop;;
let nth_take = Sections.finalize_theorem nth_take;;
let drop_nth = Sections.finalize_theorem drop_nth;;
let take_nth = Sections.finalize_theorem take_nth;;
let rot0 = Sections.finalize_theorem rot0;;
let size_rot = Sections.finalize_theorem size_rot;;
let rot_oversize = Sections.finalize_theorem rot_oversize;;
let rot_size = Sections.finalize_theorem rot_size;;
let has_rot = Sections.finalize_theorem has_rot;;
let rot_size_cat = Sections.finalize_theorem rot_size_cat;;
let rotK = Sections.finalize_theorem rotK;;
let rot_inj = Sections.finalize_theorem rot_inj;;
let rot1_cons = Sections.finalize_theorem rot1_cons;;
Sections.end_section "Sequences";;
(* Section Rev *)
Sections.begin_section "Rev";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("t", (`:(A)list`))));;
(* Lemma catrev_catl *)
let catrev_catl = Sections.section_proof ["s";"t";"u"]
`catrev (s ++ t) u = catrev t (catrev s u)`
[
((((use_arg_then2 ("u", [])) (disch_tac [])) THEN (clear_assumption "u") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma catrev_catr *)
let catrev_catr = Sections.section_proof ["s";"t";"u"]
`catrev s (t ++ u) = catrev s t ++ u`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (BETA_TAC THEN (move ["t"])) THEN ((((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("IHs", []))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma catrevE *)
let catrevE = Sections.section_proof ["s";"t"]
`catrev s t = rev s ++ t`
[
(((((use_arg_then2 ("rev", [rev]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("catrev_catr", [catrev_catr]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma rev_cons *)
let rev_cons = Sections.section_proof ["x";"s"]
`rev (x :: s) = rcons (rev s) x`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catrevE", [catrevE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rev", [rev]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma size_rev *)
let size_rev = Sections.section_proof ["s"]
`sizel (rev s) = sizel s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("catrevE", [catrevE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rcons", [size_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rev_cat *)
let rev_cat = Sections.section_proof ["s";"t"]
`rev (s ++ t) = rev t ++ rev s`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("rev", [rev]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catrev_catr", [catrev_catr]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("catrev_catl", [catrev_catl]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rev_rcons *)
let rev_rcons = Sections.section_proof ["s";"x"]
`rev (rcons s x) = x :: rev s`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rev_cat", [rev_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rev", [rev]))(thm_tac (new_rewrite [] []))))) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
(* Lemma revK *)
let revK = Sections.section_proof ["s"]
`rev (rev s) = s`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) ((repeat_tactic 1 9 (((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (simp_tac)));
(((((use_arg_then2 ("rev_cons", [rev_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rev_rcons", [rev_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_rev *)
let nth_rev = Sections.section_proof ["x0";"n";"s"]
`n < sizel s ==> nth x0 (rev s) n = nth x0 s (sizel s - SUC n)`
[
((((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN BETA_TAC) THEN (((fun arg_tac -> arg_tac (Arg_theorem (REWRITE_RULE[IMP_IMP] last_ind))) (disch_tac [])) THEN (DISCH_THEN apply_tac)));
(((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["s"]) THEN (move ["x"]) THEN (move ["IHs"]) THEN (move ["n"]));
((((use_arg_then2 ("rev_rcons", [rev_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rcons", [size_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnS", [ltnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("subSS", [subSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) (((((use_arg_then2 ("subn0", [subn0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth0", [nth0]))(thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("head", [head]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac)));
(BETA_TAC THEN (move ["lt_n_s"]));
((((fun arg_tac -> (use_arg_then2 ("subnK", [subnK])) (fun fst_arg -> (use_arg_then2 ("lt_n_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [2] []))))) THEN (((use_arg_then2 ("addSnnS", [addSnnS]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_addr", [leq_addr]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Finalization of the section Rev *)
let catrev_catl = Sections.finalize_theorem catrev_catl;;
let catrev_catr = Sections.finalize_theorem catrev_catr;;
let catrevE = Sections.finalize_theorem catrevE;;
let rev_cons = Sections.finalize_theorem rev_cons;;
let size_rev = Sections.finalize_theorem size_rev;;
let rev_cat = Sections.finalize_theorem rev_cat;;
let rev_rcons = Sections.finalize_theorem rev_rcons;;
let revK = Sections.finalize_theorem revK;;
let nth_rev = Sections.finalize_theorem nth_rev;;
Sections.end_section "Rev";;
(* Section EqSeq *)
Sections.begin_section "EqSeq";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_var (mk_var ("x0", (`:A`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(Sections.add_section_type (mk_var ("x", (`:A`))); Sections.add_section_type (mk_var ("y", (`:A`))); Sections.add_section_type (mk_var ("z", (`:A`))));;
(* Lemma eqseq_cons *)
let eqseq_cons = Sections.section_proof ["x1";"x2";"s1";"s2"]
`((x1 :: s1) = x2 :: s2) <=> (x1 = x2 /\ s1 = s2)`
[
((((fun arg_tac -> arg_tac (Arg_theorem (injectivity "list")))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma eqseq_cat *)
let eqseq_cat = Sections.section_proof ["s1";"s2";"s3";"s4"]
`sizel s1 = sizel s2 ==> (s1 ++ s3 = s2 ++ s4 <=> (s1 = s2 /\ s3 = s4))`
[
((THENL) (((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 ["x1"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x2"]) THEN (move ["s2"]) THEN (move ["_"]))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) [(arith_tac); (arith_tac); BETA_TAC]);
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("andbA", [andbA]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eqseq_rcons *)
let eqseq_rcons = Sections.section_proof ["s1";"s2";"x1";"x2"]
`(rcons s1 x1 = rcons s2 x2) <=> (s1 = s2 /\ x1 = x2)`
[
((THENL_ROT (-1)) (((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 ["y1"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y2"]) THEN (move ["s2"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbA", [andbA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s2"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["xx"]) THEN (move ["ss"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma has_filter *)
let has_filter = Sections.section_proof ["a";"s"]
`has a s <=> ~(filter a s = [])`
[
((((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`filter a s`))) (term_tac (set_tac "l")));
(((THENL) (((use_arg_then2 ("l_def", [])) (disch_tac [])) THEN (clear_assumption "l_def") THEN ((use_arg_then2 ("l", [])) (disch_tac [])) THEN (clear_assumption "l") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["l"]) THEN (move ["_"]))]) THEN (BETA_TAC THEN (move ["_"])) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_eq0 *)
let size_eq0 = Sections.section_proof ["s"]
`(sizel s = 0) <=> (s = [])`
[
(((THENL) (split_tac) [ALL_TAC; (((conv_thm_tac DISCH_THEN)(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 ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("size0nil", [size0nil])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
parse_as_infix("<-", (11, "right"));;
override_interface("<-", `MEM`);;
(* Lemma in_cons *)
let in_cons = Sections.section_proof ["y";"s";"x"]
`(x <- y :: s) <=> (x = y \/ x <- s)`
[
((repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma in_nil *)
let in_nil = Sections.section_proof ["x"]
`(x <- []) = F`
[
((repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma mem_seq1 *)
let mem_seq1 = Sections.section_proof ["x";"y"]
`(x <- [y]) <=> (x = y)`
[
(((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbF", [orbF]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_seq2 *)
let mem_seq2 = Sections.section_proof ["x";"y1";"y2"]
`(x <- [y1; y2]) <=> (x = y1 \/ x = y2)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbF", [orbF]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_seq3 *)
let mem_seq3 = Sections.section_proof ["x";"y1";"y2";"y3"]
`(x <- [y1; y2; y3]) <=> (x = y1 \/ x = y2 \/ x = y3)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbF", [orbF]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_seq4 *)
let mem_seq4 = Sections.section_proof ["x";"y1";"y2";"y3";"y4"]
`(x <- [y1; y2; y3; y4]) <=> (x = y1 \/ x = y2 \/ x = y3 \/ x = y4)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbF", [orbF]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_cat *)
let mem_cat = Sections.section_proof ["x";"s1";"s2"]
`(x <- s1 ++ s2) <=> (x <- s1 \/ x <- s2)`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) (((((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orFb", [orFb]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(((((use_arg_then2 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbA", [orbA]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma mem_rcons *)
let mem_rcons = Sections.section_proof ["s";"y"]
`!x. x <- rcons s y <=> x <- y :: s`
[
((BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac) THEN (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_seq1", [mem_seq1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbC", [orbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_head *)
let mem_head = Sections.section_proof ["x";"s"]
`x <- x :: s`
[
(((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma mem_last *)
let mem_last = Sections.section_proof ["x";"s"]
`last x s <- x :: s`
[
(((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_rcons", [mem_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_head", [mem_head]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_behead *)
let mem_behead = Sections.section_proof ["s"]
`!x. x <- behead s ==> x <- s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["_"]) THEN (move ["x"]))]) THEN ((((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("in_cons", [in_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma mem_belast *)
let mem_belast = Sections.section_proof ["s";"y"]
`!x. x <- belast y s ==> x <- y :: s`
[
((BETA_TAC THEN (move ["x"]) THEN (move ["ys'x"])) THEN ((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_rcons", [mem_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_behead", [mem_behead]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma mem_nth *)
let mem_nth = Sections.section_proof ["s";"n"]
`n < sizel s ==> nth x0 s n <- 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mem_head", [mem_head]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["sz_s"]));
((((use_arg_then2 ("mem_behead", [mem_behead]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma mem_take *)
let mem_take = Sections.section_proof ["s";"x"]
`x <- take n0 s ==> x <- s`
[
((BETA_TAC THEN (move ["s0x"])) THEN ((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (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 (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_drop *)
let mem_drop = Sections.section_proof ["s";"x"]
`x <- dropl n0 s ==> x <- s`
[
((BETA_TAC THEN (move ["s0'x"])) THEN ((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (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 (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_rev *)
let mem_rev = Sections.section_proof ["s"]
`!x. x <- rev s <=> x <- s`
[
((THENL_FIRST) ((BETA_TAC THEN (move ["y"])) THEN ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))])) (((((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac)));
(((((use_arg_then2 ("rev_cons", [rev_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_rcons", [mem_rcons]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Section Filters *)
Sections.begin_section "Filters";;
(Sections.add_section_var (mk_var ("a", (`:A -> bool`))));;
(* Lemma hasP *)
let hasP = Sections.section_proof ["s"]
`(?x. x <- s /\ a x) <=> has a s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
((THENL_FIRST) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ay"])) (((use_arg_then2 ("y", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("mem_head", [mem_head]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((THENL_ROT (-1)) ((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((split_tac) THEN ALL_TAC THEN (case THEN ((move ["x"]) THEN (case THEN ((move ["ysx"]) THEN (move ["ax"]))))))));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN ((((use_arg_then2 ("mem_behead", [mem_behead]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("ysx", [])) (disch_tac [])) THEN (clear_assumption "ysx") THEN BETA_TAC) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y:A`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN ((simp_tac THEN TRY done_tac)) THEN (move ["xy"]));
((((use_arg_then2 ("ax", [])) (disch_tac [])) THEN (clear_assumption "ax") THEN BETA_TAC) THEN ((((use_arg_then2 ("xy", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ay", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma hasPn *)
let hasPn = Sections.section_proof ["s"]
`(!x. x <- s ==> ~(a x)) <=> ~has a s`
[
((THENL_ROT (1)) ((split_tac) THEN (move ["not_a_s"])));
((BETA_TAC THEN (move ["x"]) THEN (move ["s_x"])) THEN (((use_arg_then2 ("not_a_s", [])) (disch_tac [])) THEN (clear_assumption "not_a_s") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (move ["a_x"])));
((((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
((((((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("implybF", [implybF]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (case THEN ((move ["x"]) THEN (case THEN (move ["s_x"]))))) THEN (((use_arg_then2 ("implybF", [implybF]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("not_a_s", [])) (disch_tac [])) THEN (clear_assumption "not_a_s") THEN (exact_tac)) THEN (done_tac));
];;
(* Lemma allP *)
let allP = Sections.section_proof ["s"]
`(!x. x <- s ==> a x) <=> (all a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((THENL_ROT (-1)) (((((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (split_tac)));
(BETA_TAC THEN (case THEN ((move ["h"]) THEN (move ["ax"]))) THEN (move ["y"]) THEN ((THENL) case [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))); (move ["ys"])]));
(((use_arg_then2 ("h", [])) (disch_tac [])) THEN (clear_assumption "h") THEN (exact_tac));
(BETA_TAC THEN (move ["h"]));
((THENL_FIRST) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) (BETA_TAC THEN (move ["ax"])));
((((((use_arg_then2 ("ax", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (move ["y"]) THEN (move ["ys"])) THEN (((use_arg_then2 ("h", [])) (disch_tac [])) THEN (clear_assumption "h") THEN (exact_tac)) THEN (done_tac));
(((use_arg_then2 ("h", [])) (disch_tac [])) THEN (clear_assumption "h") THEN (exact_tac));
];;
(* Lemma allPn *)
let allPn = Sections.section_proof ["s"]
`(?x. x <- s /\ ~a x) <=> ~all a s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("in_cons", [in_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (split_tac));
(BETA_TAC THEN (case THEN ((move ["y"]) THEN (case THEN ((move ["ay"]) THEN ((THENL) case [(move ["eq"]); (move ["mem"])]))))));
((((use_arg_then2 ("ay", [])) (disch_tac [])) THEN (clear_assumption "ay") THEN BETA_TAC) THEN ((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
((DISJ2_TAC) THEN ((use_arg_then2 ("y", [])) (term_tac exists_tac)) THEN (done_tac));
((THENL_FIRST) ((THENL) case [(move ["nax"]); (case THEN ((move ["y"]) THEN (case THEN ((move ["ys"]) THEN (move ["nay"])))))]) ((((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (simp_tac)) THEN (done_tac)));
(((use_arg_then2 ("y", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma mem_filter *)
let mem_filter = Sections.section_proof ["x";"s"]
`(x <- filter a s) <=> (a x /\ x <- s)`
[
((((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("MEM", [MEM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((use_arg_then2 ("fun_if", [fun_if]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(a:A->bool) y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ay"])) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y:A`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN ((simp_tac THEN TRY done_tac))) THEN (done_tac));
];;
(* Finalization of the section Filters *)
let hasP = Sections.finalize_theorem hasP;;
let hasPn = Sections.finalize_theorem hasPn;;
let allP = Sections.finalize_theorem allP;;
let allPn = Sections.finalize_theorem allPn;;
let mem_filter = Sections.finalize_theorem mem_filter;;
Sections.end_section "Filters";;
(* Lemma eq_in_filter *)
let eq_in_filter = Sections.section_proof ["a1";"a2";"s"]
`(!x. x <- s ==> a1 x = a2 x) ==> filter a1 s = filter a2 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (move ["eq_a"])));
(((((use_arg_then2 ("eq_a", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mem_head", [mem_head]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (move ["y"]) THEN (move ["s_y"]));
((((use_arg_then2 ("eq_a", [])) (disch_tac [])) THEN (clear_assumption "eq_a") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("mem_behead", [mem_behead]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma eq_has_r *)
let eq_has_r = Sections.section_proof ["s1";"s2"]
`(!x. x <- s1 <=> x <- s2) ==> (!a. has a s1 <=> has a s2)`
[
(BETA_TAC THEN (move ["Es12"]) THEN (move ["a"]));
((split_tac) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ALL_TAC THEN (case THEN ((move ["x"]) THEN (case THEN ((move ["Hx"]) THEN (move ["Hax"])))))));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("Es12", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("Es12", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma eq_all_r *)
let eq_all_r = Sections.section_proof ["s1";"s2"]
`(!x. x <- s1 <=> x <- s2) ==> (!a. all a s1 = all a s2)`
[
((BETA_TAC THEN (move ["Es12"]) THEN (move ["a"])) THEN (repeat_tactic 1 9 (((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((split_tac) THEN (move ["Hs"]) THEN (move ["x"]) THEN (move ["Hx"])));
((((use_arg_then2 ("Hs", [])) (disch_tac [])) THEN (clear_assumption "Hs") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("Es12", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
((((use_arg_then2 ("Hs", [])) (disch_tac [])) THEN (clear_assumption "Hs") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("Es12", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_sym *)
let has_sym = Sections.section_proof ["s1";"s2"]
`has (\x. x <- s1) s2 = has (\x. x <- s2) s1`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (simp_tac) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_pred1 *)
let has_pred1 = Sections.section_proof ["x";"s"]
`has (pred1 x) s <=> x <- s`
[
(((((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN ((THENL) (split_tac) [((case THEN ((move ["y"]) THEN (case THEN ((move ["ys"]) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))))))) THEN ((TRY done_tac))); (move ["xs"])]));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma all_pred1P *)
let all_pred1P = Sections.section_proof ["x";"s"]
`(s = nseq (sizel s) x) <=> (all (pred1 x) s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((THENL_ROT (-1)) ((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [(((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))); (move ["ne_xy"])]));
(((((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN ((((use_arg_then2 ("ne_xy", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("andFb", [andFb]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
(((((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [1] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nseq", [nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ncons", [ncons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_pred1_constant *)
let all_pred1_constant = Sections.section_proof ["x";"s"]
`all (pred1 x) s ==> constant s`
[
((((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) THEN ((((use_arg_then2 ("constant", [constant]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma all_pred1_nseq *)
let all_pred1_nseq = Sections.section_proof ["x";"y";"n"]
`all (pred1 x) (nseq n y) <=> (n = 0 \/ x = y)`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((simp_tac THEN TRY done_tac))));
(((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`y = x`)])))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orFb", [orFb]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("andb_idr", [andb_idr])) (disch_tac [])) THEN (clear_assumption "andb_idr") THEN (DISCH_THEN apply_tac) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))));
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma constant_nseq *)
let constant_nseq = Sections.section_proof ["n";"x"]
`constant (nseq n x)`
[
(((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN case) [ALL_TAC; (move ["n"])]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("constant", [constant]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((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 ("all_pred1_nseq", [all_pred1_nseq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma constantP *)
let constantP = Sections.section_proof ["s"]
`(?x. s = nseq (sizel s) x) <=> (constant s)`
[
((THENL_FIRST) ((THENL) (split_tac) [(case THEN ((move ["x"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))); ALL_TAC]) ((((use_arg_then2 ("constant_nseq", [constant_nseq]))(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 ["x"]) THEN (move ["s"]))]) THEN ((((use_arg_then2 ("constant", [constant]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac))) ((EXISTS_TAC `x0:A`) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac)));
(((((use_arg_then2 ("all_pred1P", [all_pred1P]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (move ["def_s"])) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)));
((((use_arg_then2 ("def_s", []))(thm_tac (new_rewrite [1] [])))) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nil_uniq *)
let nil_uniq = Sections.section_proof []
`uniq ([]:(A)list)`
[
((((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma cons_uniq *)
let cons_uniq = Sections.section_proof ["x";"s"]
`uniq (x :: s) <=> ~(x <- s) /\ uniq s`
[
((((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma cat_uniq *)
let cat_uniq = Sections.section_proof ["s1";"s2"]
`uniq (s1 ++ s2) <=> uniq s1 /\ ~ has (\x. x <- s1) s2 /\ uniq s2`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) (((((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred0", [pred0]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_pred0", [has_pred0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nil_uniq", [nil_uniq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((use_arg_then2 ("has_sym", [has_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_cons", [has_cons]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("negb_or", [negb_or]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_sym", [has_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("andbA", [andbA]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac));
((((use_arg_then2 ("andbAC", [andbAC]))(thm_tac (new_rewrite [] [(`_ /\ uniq s1`)])))) THEN (done_tac));
];;
(* Lemma uniq_catC *)
let uniq_catC = Sections.section_proof ["s1";"s2"]
`uniq (s1 ++ s2) = uniq (s2 ++ s1)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("cat_uniq", [cat_uniq]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_sym", [has_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbCA", [andbCA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbA", [andbA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma uniq_catCA *)
let uniq_catCA = Sections.section_proof ["s1";"s2";"s3"]
`uniq (s1 ++ s2 ++ s3) = uniq (s2 ++ s1 ++ s3)`
[
(repeat_tactic 1 9 (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] [])))));
(((repeat_tactic 1 9 (((use_arg_then2 ("uniq_catC", [uniq_catC]))(gsym_then (thm_tac (new_rewrite [] [(`uniq (cat _ s3)`)])))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat_uniq", [cat_uniq]))(thm_tac (new_rewrite [] [(`uniq (cat s3 _)`)]))))) THEN (((use_arg_then2 ("uniq_catC", [uniq_catC]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("has_cat", [has_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("orbC", [orbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rcons_uniq *)
let rcons_uniq = Sections.section_proof ["s";"x"]
`uniq (rcons s x) <=> (~(x <- s) /\ uniq s)`
[
(((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("uniq_catC", [uniq_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma filter_uniq *)
let filter_uniq = Sections.section_proof ["s";"a"]
`uniq s ==> uniq (filter a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((THENL_ROT (-1)) (((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)); (move ["nax"])]) THEN (BETA_TAC THEN (case THEN ((move ["Hx"]) THEN (move ["Hs"]))))));
(((((use_arg_then2 ("nax", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN (exact_tac)) THEN (done_tac));
((((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((((use_arg_then2 ("mem_filter", [mem_filter]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("negbTE", [negbTE])) (fun fst_arg -> (use_arg_then2 ("Hx", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbF", [andbF]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rot_uniq *)
let rot_uniq = Sections.section_proof ["s"]
`uniq (rot n0 s) = uniq s`
[
(((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("uniq_catC", [uniq_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rev_uniq *)
let rev_uniq = Sections.section_proof ["s"]
`uniq (rev s) = uniq s`
[
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) (((((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (done_tac)));
(((((use_arg_then2 ("rev_cons", [rev_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cat_uniq", [cat_uniq]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_cons", [has_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nil_uniq", [nil_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_nil", [has_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_or", [negb_or]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_rev", [mem_rev]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_uniq_mem *)
let count_uniq_mem = Sections.section_proof ["s";"x"]
`uniq s ==> count (pred1 x) s = if (x <- s) then 1 else 0`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
((((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["Hy"]))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`y = x`)])))));
(((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)); ALL_TAC]) THEN ((((use_arg_then2 ("Hy", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("addn0", [addn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
let undup = define `undup [] = [] /\
undup (x :: s') = if x <- s' then undup s' else x :: undup s'`;;
(* Lemma size_undup *)
let size_undup = Sections.section_proof ["s"]
`sizel (undup s) <= sizel s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("leqnn", [leqnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x <- s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(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 ("ltnW", [ltnW]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_undup *)
let mem_undup = Sections.section_proof ["s"]
`!x. x <- undup s <=> x <- s`
[
((BETA_TAC THEN (move ["x"])) THEN ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`y <- s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["Hy"])) THEN ((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("MEM", [MEM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma undup_uniq *)
let undup_uniq = Sections.section_proof ["s"]
`uniq (undup s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x <- s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) THEN (((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma undup_id *)
let undup_id = Sections.section_proof ["s"]
`uniq s ==> undup s = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((((use_arg_then2 ("undup", [undup]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((simp_tac THEN TRY done_tac))) THEN ALL_TAC THEN (case THEN ((move ["Hx"]) THEN (move ["Hs"])))));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma ltn_size_undup *)
let ltn_size_undup = Sections.section_proof ["s"]
`(sizel (undup s) < sizel s) <=> ~ uniq s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("undup", [undup]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x <- s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case) THEN (((simp_tac THEN TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltnS", [ltnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_undup", [size_undup]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
let index = new_definition `indexl x = find (pred1 x)`;;
(* Lemma index_size *)
let index_size = Sections.section_proof ["x";"s"]
`indexl x s <= sizel s`
[
(((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("find_size", [find_size]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_mem *)
let index_mem = Sections.section_proof ["x";"s"]
`(indexl x s < sizel s) <=> (x <- s)`
[
(((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_find", [has_find]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_index *)
let nth_index = Sections.section_proof ["x";"s"]
`x <- s ==> nth x0 s (indexl x s) = x`
[
((((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (fun arg_tac -> (use_arg_then2 ("nth_find", [nth_find])) (fun fst_arg -> (use_arg_then2 ("x0", [])) (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 ((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma index_cat *)
let index_cat = Sections.section_proof ["x";"s1";"s2"]
`indexl x (s1 ++ s2) = if x <- s1 then indexl x s1 else sizel s1 + indexl x s2`
[
(((((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("find_cat", [find_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_pred1", [has_pred1]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_uniq *)
let index_uniq = Sections.section_proof ["i";"s"]
`i < sizel s ==> uniq s ==> indexl (nth x0 s i) s = i`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN ((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]));
(((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("index", [index]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnS", [ltnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] []))))) THEN (move ["lt_i_s"]) THEN (case THEN (move ["not_s_x"])));
(((DISCH_THEN (fun snd_th -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("IHs", [])) (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 ("lt_i_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 (((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("index", [index]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (simp_tac)));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = nth x0 s i`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["x_eq"]));
(((fun arg_tac -> (use_arg_then2 ("mem_nth", [mem_nth])) (fun fst_arg -> (use_arg_then2 ("lt_i_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun arg -> thm_tac MP_TAC arg THEN ALL_TAC)) THEN ((((use_arg_then2 ("x_eq", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("negbTE", [negbTE])) (fun fst_arg -> (use_arg_then2 ("not_s_x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma index_head *)
let index_head = Sections.section_proof ["x";"s"]
`indexl x (x :: s) = 0`
[
(((((use_arg_then2 ("index", [index]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma index_last *)
let index_last = Sections.section_proof ["x";"s"]
`uniq (x :: s) ==> indexl (last x s) (x :: s) = sizel s`
[
((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rcons_uniq", [rcons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index_cat", [index_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_belast", [size_belast]))(thm_tac (new_rewrite [] [])))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`last x s <- belast x s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac));
(((((use_arg_then2 ("index", [index]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("addn0", [addn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_uniq *)
let nth_uniq = Sections.section_proof ["s";"i";"j"]
`i < sizel s ==> j < sizel s ==> uniq s ==> (nth x0 s i = nth x0 s j) = (i = j)`
[
((BETA_TAC THEN (move ["lt_i_s"]) THEN (move ["lt_j_s"]) THEN (move ["Us"])) THEN ((THENL) (split_tac) [(move ["eq_sij"]); ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))]));
(((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("index_uniq", [index_uniq])) (fun fst_arg -> (use_arg_then2 ("lt_i_s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("Us", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eq_sij", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("index_uniq", [index_uniq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_rot *)
let mem_rot = Sections.section_proof ["s"]
`!x. x <- rot n0 s <=> x <- s`
[
((BETA_TAC THEN (move ["x"])) THEN ((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (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 [2] [(`s`)]))))) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("orbC", [orbC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eqseq_rot *)
let eqseq_rot = Sections.section_proof ["s1";"s2"]
`(rot n0 s1 = rot n0 s2) <=> (s1 = s2)`
[
(((THENL) (split_tac) [ALL_TAC; ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))]) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("rot_inj", [rot_inj])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma rot_to *)
let rot_to = Sections.section_proof ["s";"x"]
`x <- s ==> ?i s'. rot i s = x :: s'`
[
((BETA_TAC THEN (move ["s_x"])) THEN ((fun arg_tac -> arg_tac (Arg_term (`indexl (x:A) s`))) (term_tac (set_tac "i"))));
(((use_arg_then2 ("i", [])) (term_tac exists_tac)) THEN ((fun arg_tac -> arg_tac (Arg_term (`dropl (SUC i) s ++ take i s`))) (term_tac exists_tac)));
(((((use_arg_then2 ("cat_cons", [cat_cons]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("i_def", []))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((fun arg_tac -> arg_tac (Arg_term (`take _1 _2`))) (term_tac (set_tac "r"))));
(((use_arg_then2 ("r_def", [])) (disch_tac [])) THEN (clear_assumption "r_def") THEN ((use_arg_then2 ("i_def", [])) (disch_tac [])) THEN (clear_assumption "i_def") THEN BETA_TAC THEN (move ["_"]) THEN (move ["_"]));
(((THENL) (((use_arg_then2 ("s_x", [])) (disch_tac [])) THEN (clear_assumption "s_x") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("in_nil", [in_nil]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)));
((((use_arg_then2 ("index_head", [index_head]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop0", [drop0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop_cons", [drop_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("drop0", [drop0]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((((use_arg_then2 ("index", [index]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("pred1", [pred1]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("index", [index]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("drop_cons", [drop_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (move ["_"])) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section EqSeq *)
let eqseq_cons = Sections.finalize_theorem eqseq_cons;;
let eqseq_cat = Sections.finalize_theorem eqseq_cat;;
let eqseq_rcons = Sections.finalize_theorem eqseq_rcons;;
let has_filter = Sections.finalize_theorem has_filter;;
let size_eq0 = Sections.finalize_theorem size_eq0;;
let in_cons = Sections.finalize_theorem in_cons;;
let in_nil = Sections.finalize_theorem in_nil;;
let mem_seq1 = Sections.finalize_theorem mem_seq1;;
let mem_seq2 = Sections.finalize_theorem mem_seq2;;
let mem_seq3 = Sections.finalize_theorem mem_seq3;;
let mem_seq4 = Sections.finalize_theorem mem_seq4;;
let mem_cat = Sections.finalize_theorem mem_cat;;
let mem_rcons = Sections.finalize_theorem mem_rcons;;
let mem_head = Sections.finalize_theorem mem_head;;
let mem_last = Sections.finalize_theorem mem_last;;
let mem_behead = Sections.finalize_theorem mem_behead;;
let mem_belast = Sections.finalize_theorem mem_belast;;
let mem_nth = Sections.finalize_theorem mem_nth;;
let mem_take = Sections.finalize_theorem mem_take;;
let mem_drop = Sections.finalize_theorem mem_drop;;
let mem_rev = Sections.finalize_theorem mem_rev;;
let hasP = Sections.finalize_theorem hasP;;
let hasPn = Sections.finalize_theorem hasPn;;
let allP = Sections.finalize_theorem allP;;
let allPn = Sections.finalize_theorem allPn;;
let mem_filter = Sections.finalize_theorem mem_filter;;
let eq_in_filter = Sections.finalize_theorem eq_in_filter;;
let eq_has_r = Sections.finalize_theorem eq_has_r;;
let eq_all_r = Sections.finalize_theorem eq_all_r;;
let has_sym = Sections.finalize_theorem has_sym;;
let has_pred1 = Sections.finalize_theorem has_pred1;;
let all_pred1P = Sections.finalize_theorem all_pred1P;;
let all_pred1_constant = Sections.finalize_theorem all_pred1_constant;;
let all_pred1_nseq = Sections.finalize_theorem all_pred1_nseq;;
let constant_nseq = Sections.finalize_theorem constant_nseq;;
let constantP = Sections.finalize_theorem constantP;;
let nil_uniq = Sections.finalize_theorem nil_uniq;;
let cons_uniq = Sections.finalize_theorem cons_uniq;;
let cat_uniq = Sections.finalize_theorem cat_uniq;;
let uniq_catC = Sections.finalize_theorem uniq_catC;;
let uniq_catCA = Sections.finalize_theorem uniq_catCA;;
let rcons_uniq = Sections.finalize_theorem rcons_uniq;;
let filter_uniq = Sections.finalize_theorem filter_uniq;;
let rot_uniq = Sections.finalize_theorem rot_uniq;;
let rev_uniq = Sections.finalize_theorem rev_uniq;;
let count_uniq_mem = Sections.finalize_theorem count_uniq_mem;;
let size_undup = Sections.finalize_theorem size_undup;;
let mem_undup = Sections.finalize_theorem mem_undup;;
let undup_uniq = Sections.finalize_theorem undup_uniq;;
let undup_id = Sections.finalize_theorem undup_id;;
let ltn_size_undup = Sections.finalize_theorem ltn_size_undup;;
let index_size = Sections.finalize_theorem index_size;;
let index_mem = Sections.finalize_theorem index_mem;;
let nth_index = Sections.finalize_theorem nth_index;;
let index_cat = Sections.finalize_theorem index_cat;;
let index_uniq = Sections.finalize_theorem index_uniq;;
let index_head = Sections.finalize_theorem index_head;;
let index_last = Sections.finalize_theorem index_last;;
let nth_uniq = Sections.finalize_theorem nth_uniq;;
let mem_rot = Sections.finalize_theorem mem_rot;;
let eqseq_rot = Sections.finalize_theorem eqseq_rot;;
let rot_to = Sections.finalize_theorem rot_to;;
Sections.end_section "EqSeq";;
(* Section NseqthTheory *)
Sections.begin_section "NseqthTheory";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(* Lemma nthP *)
let nthP = Sections.section_proof ["s";"x";"x0"]
`(?i. i < sizel s /\ nth x0 s i = x) <=> (x <- s)`
[
((THENL_FIRST) ((THENL) (split_tac) [(case THEN ((move ["n"]) THEN (case THEN ((move ["Hn"]) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] []))))))))); (move ["Hx"])]) ((((use_arg_then2 ("mem_nth", [mem_nth])) (disch_tac [])) THEN (clear_assumption "mem_nth") THEN (DISCH_THEN apply_tac)) THEN (done_tac)));
(((fun arg_tac -> arg_tac (Arg_term (`indexl x s`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("index_mem", [index_mem]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hx", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index])) (disch_tac [])) THEN (clear_assumption "nth_index") THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Lemma has_nthP *)
let has_nthP = Sections.section_proof ["a";"s";"x0"]
`(?i. i < sizel s /\ a (nth x0 s i)) <=> (has a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("andFb", [andFb]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ax"]));
(((fun arg_tac -> arg_tac (Arg_term (`0`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0Sn", [ltn0Sn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((THENL_ROT (-1)) ((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((THENL) (split_tac) [(case THEN ALL_TAC); (case THEN (move ["i"]))])));
((BETA_TAC THEN (case THEN ((move ["i_s"]) THEN (move ["anth"])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`SUC i`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((THENL_FIRST) (((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) ((((use_arg_then2 ("ax", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) 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 ALL_TAC THEN (case THEN ((move ["i_s"]) THEN (move ["anth"])))) THEN ((use_arg_then2 ("i", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma all_nthP *)
let all_nthP = Sections.section_proof ["a";"s";"x0"]
`(!i. i < sizel s ==> a (nth x0 s i)) <=> (all a s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
((THENL_ROT (-1)) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ax"])));
((((use_arg_then2 ("NOT_FORALL_THM", [NOT_FORALL_THM]))(thm_tac (new_rewrite [] [])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`0`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltn0Sn", [ltn0Sn]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((split_tac) THEN (move ["IH"]) THEN (move ["i"]) THEN (move ["i_s"])));
((((fun arg_tac -> (use_arg_then2 ("IH", [])) (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 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (exact_tac) THEN (done_tac));
(((THENL) (((use_arg_then2 ("i_s", [])) (disch_tac [])) THEN (clear_assumption "i_s") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN elim) [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY 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 ("IH", [])) (disch_tac [])) THEN (clear_assumption "IH") THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Finalization of the section NseqthTheory *)
let nthP = Sections.finalize_theorem nthP;;
let has_nthP = Sections.finalize_theorem has_nthP;;
let all_nthP = Sections.finalize_theorem all_nthP;;
Sections.end_section "NseqthTheory";;
(* Lemma set_nth_default *)
let set_nth_default = Sections.section_proof ["s";"y0";"x0";"n"]
`n < sizel s ==> nth (x0:A) s n = nth y0 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 ["y"]) THEN (move ["s'"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (done_tac));
];;
(* Lemma headI *)
let headI = Sections.section_proof ["s";"x"]
`rcons s x = headl x s :: behead (rcons s (x:A))`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["s"]) THEN (move ["x"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("rcons", [rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("head", [head]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_incr_nth *)
let nth_incr_nth = Sections.section_proof ["v";"i";"j"]
`nth 0 (incr_nth v i) j = (if (i = j) then 1 else 0) + nth 0 v j`
[
(((THENL) (((use_arg_then2 ("j", [])) (disch_tac [])) THEN (clear_assumption "j") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("v", [])) (disch_tac [])) THEN (clear_assumption "v") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["v"]) THEN (move ["IHv"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["j"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("incr_nth", [incr_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("addn0", [addn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("eqS0", [eqS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add1n", [add1n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(arith_tac);
(((THENL) (((use_arg_then2 ("j", [])) (disch_tac [])) THEN (clear_assumption "j") THEN ((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN elim) [ALL_TAC; ((move ["i"]) THEN (move ["IHv"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["j"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
(arith_tac);
(arith_tac);
(((((use_arg_then2 ("IHv", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`0 = SUC j`)])))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("IHv", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_incr_nth *)
let size_incr_nth = Sections.section_proof ["v";"i"]
`sizel (incr_nth v i) = if i < sizel v then sizel v else SUC i`
[
(((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((use_arg_then2 ("v", [])) (disch_tac [])) THEN (clear_assumption "v") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["v"]) THEN (move ["IHv"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("incr_nth", [incr_nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_ncons", [size_ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("ONE", [ONE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("addn1", [addn1]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("ltn0Sn", [ltn0Sn]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
((((use_arg_then2 ("IHv", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] [])))));
(((use_arg_then2 ("fun_if", [fun_if])) (thm_tac apply_tac)) THEN (done_tac));
];;
(* Section PermSeq *)
Sections.begin_section "PermSeq";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("s1", (`:(A)list`))));;
(* Lemma perm_eqP *)
let perm_eqP = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 <=> (!a. count a s1 = count a s2)`
[
((THENL_LAST) (((((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 ((THENL) (split_tac) [((move ["eq_cnt1"]) THEN (move ["a"])); ((move ["eq_cnt"]) THEN (move ["x"]) THEN (move ["_"]))])) (exact_tac));
((((fun arg_tac -> (use_arg_then2 ("ltnSn", [ltnSn])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`count a (s1 ++ s2)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN ((use_arg_then2 ("a", [])) (disch_tac [1; 3; 4])) THEN (clear_assumption "a") THEN ((fun arg_tac -> arg_tac (Arg_term (`SUC _`))) (disch_tac [])) THEN elim) THEN (((repeat_tactic 0 10 (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN (move ["n"]) THEN (move ["IHn"]) THEN (move ["a"]) THEN (move ["le_an"])));
(((fun arg_tac -> (use_arg_then2 ("posnP", [posnP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`count a (s1 ++ s2)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case);
((((((use_arg_then2 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn_eq0", [addn_eq0]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ALL_TAC) 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 ("has_count", [has_count]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("hasP", [hasP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ALL_TAC THEN (case THEN (move ["x"])) THEN (case THEN ((move ["s12x"]) THEN (move ["a_x"])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`predD1 a x`))) (term_tac (set_tac "a'"))));
((fun arg_tac -> arg_tac (Arg_term (`!s. count a s = count (pred1 x) s + count a' s`))) (term_tac (have_gen_tac [](move ["cnt_a'"]))));
(BETA_TAC THEN (move ["s"]));
((((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] [])))) THEN (((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)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 2 0 (((use_arg_then2 ("count_filter", [count_filter]))(thm_tac (new_rewrite [] []))))));
((repeat_tactic 1 9 (((use_arg_then2 ("filter_predI", [filter_predI]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("count_filter", [count_filter]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`predI (\x'. ~pred1 x x') a = predD1 a x`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))));
(((((use_arg_then2 ("predI", [predI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predD1", [predD1]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("predD", [predD]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
((((use_arg_then2 ("a'_def", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqn_addr", [eqn_addr]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("eq_count", [eq_count])) (disch_tac [])) THEN (clear_assumption "eq_count") THEN (DISCH_THEN apply_tac) THEN (move ["y"])) THEN ((((use_arg_then2 ("predI", [predI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN ((THENL) (split_tac) [(case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) THEN (done_tac));
((repeat_tactic 1 9 (((use_arg_then2 ("cnt_a'", []))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("eq_cnt1", [])) (fun fst_arg -> (use_arg_then2 ("s12x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (use_arg_then2 ("IHn", [])) (fun fst_arg -> (use_arg_then2 ("a'", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnS", [ltnS]))(gsym_then (thm_tac (new_rewrite [] []))))));
((((use_arg_then2 ("le_an", [])) (disch_tac [])) THEN (clear_assumption "le_an") THEN BETA_TAC) THEN (repeat_tactic 1 9 (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leq_trans", [leq_trans])) (disch_tac [])) THEN (clear_assumption "leq_trans") THEN (DISCH_THEN apply_tac)));
(((((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltnS", [ltnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cnt_a'", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add1n", [add1n]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leq_add2r", [leq_add2r]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ONE", [ONE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_count", [has_count]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("has_pred1", [has_pred1]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_refl *)
let perm_eq_refl = Sections.section_proof ["s"]
`perm_eq s s`
[
((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma perm_eq_sym *)
let perm_eq_sym = Sections.section_proof []
`!s1 s2. perm_eq s1 s2 = perm_eq s2 s1`
[
((BETA_TAC THEN (move ["s1"]) THEN (move ["s2"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`!a. _ a`)]))))) THEN (done_tac));
];;
(* Lemma perm_eq_trans *)
let perm_eq_trans = Sections.section_proof []
`!s2 s1 s3. perm_eq s1 s2 ==> perm_eq s2 s3 ==> perm_eq s1 s3`
[
((BETA_TAC THEN (move ["s2"]) THEN (move ["s1"]) THEN (move ["s3"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (move ["eq12"]) THEN (move ["eq23"]) THEN (move ["a"])));
(((((use_arg_then2 ("eq12", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq23", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eqlP *)
let perm_eqlP = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 <=> (!s. perm_eq s1 s = perm_eq s2 s)`
[
((THENL_LAST) ((THENL) (split_tac) [((move ["eq12"]) THEN (move ["s3"])); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) ((((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((THENL_LAST) (split_tac) (((use_arg_then2 ("perm_eq_trans", [perm_eq_trans])) (disch_tac [])) THEN (clear_assumption "perm_eq_trans") THEN (exact_tac)));
((repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("perm_eq_sym", [perm_eq_sym])) (fun fst_arg -> (use_arg_then2 ("s3", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [(`perm_eq _ s3`)])))))) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("perm_eq_trans", [perm_eq_trans])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN (DISCH_THEN apply_tac) THEN (done_tac));
];;
(* Lemma perm_eqrP *)
let perm_eqrP = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 <=> (!s. perm_eq s s1 = perm_eq s s2)`
[
((THENL_LAST) ((THENL) (split_tac) [ALL_TAC; (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))]) ((((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("perm_eqlP", [perm_eqlP]))(thm_tac (new_rewrite [] [])))) THEN (move ["eq12"]) THEN (move ["s3"]));
(((repeat_tactic 1 9 (((fun arg_tac -> (use_arg_then2 ("perm_eq_sym", [perm_eq_sym])) (fun fst_arg -> (use_arg_then2 ("s3", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [(`perm_eq s3 _`)]))))) THEN (((use_arg_then2 ("eq12", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_catC *)
let perm_catC = Sections.section_proof ["s1";"s2"]
`!s. perm_eq (s1 ++ s2) s = perm_eq (s2 ++ s1) s`
[
((((((use_arg_then2 ("perm_eqlP", [perm_eqlP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN (move ["a"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("addnC", [addnC]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_cat2l *)
let perm_cat2l = Sections.section_proof ["s1";"s2";"s3"]
`perm_eq (s1 ++ s2) (s1 ++ s3) = perm_eq s2 s3`
[
((repeat_tactic 1 9 (((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] []))))) THEN ((split_tac) THEN (move ["eq23"]) THEN (move ["a"])));
((((fun arg_tac -> (use_arg_then2 ("eq23", [])) (fun fst_arg -> (use_arg_then2 ("a", [])) (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 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eqn_addl", [eqn_addl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("eq23", [])) (fun fst_arg -> (use_arg_then2 ("a", [])) (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 ("count_cat", [count_cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eqn_addl", [eqn_addl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_cons *)
let perm_cons = Sections.section_proof ["x";"s1";"s2"]
`perm_eq (x :: s1) (x :: s2) = perm_eq s1 s2`
[
((((fun arg_tac -> (use_arg_then2 ("perm_cat2l", [perm_cat2l])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`[x]`))) (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 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] [])))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_cat2r *)
let perm_cat2r = Sections.section_proof ["s1";"s2";"s3"]
`perm_eq (s2 ++ s1) (s3 ++ s1) = perm_eq s2 s3`
[
((repeat_tactic 2 0 (((((use_arg_then2 ("perm_eq_sym", [perm_eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_catC", [perm_catC]))(thm_tac (new_rewrite [] []))))))) THEN (((use_arg_then2 ("perm_cat2l", [perm_cat2l]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma perm_catAC *)
let perm_catAC = Sections.section_proof ["s1";"s2";"s3"]
`!s. perm_eq ((s1 ++ s2) ++ s3) s = perm_eq ((s1 ++ s3) ++ s2) s`
[
(((((use_arg_then2 ("perm_eqlP", [perm_eqlP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("catA", [catA]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("perm_cat2l", [perm_cat2l]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_catC", [perm_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_catCA *)
let perm_catCA = Sections.section_proof ["s1";"s2";"s3"]
`!s. perm_eq (s1 ++ s2 ++ s3) s = perm_eq (s2 ++ s1 ++ s3) s`
[
(((((use_arg_then2 ("perm_eqlP", [perm_eqlP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("perm_cat2r", [perm_cat2r]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_catC", [perm_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_rcons *)
let perm_rcons = Sections.section_proof ["x";"s"]
`!s2. perm_eq (rcons s x) s2 = perm_eq (x :: s) s2`
[
((BETA_TAC THEN (move ["s2"])) THEN ((((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("perm_catC", [perm_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat1s", [cat1s]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_rot *)
let perm_rot = Sections.section_proof ["n";"s"]
`!s2. perm_eq (rot n s) s2 = perm_eq s s2`
[
((BETA_TAC THEN (move ["s2"])) THEN ((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_catC", [perm_catC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_rotr *)
let perm_rotr = Sections.section_proof ["n";"s"]
`!s2. perm_eq (rotr n s) s2 = perm_eq s s2`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_rot", [perm_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_filterC *)
let perm_filterC = Sections.section_proof ["a";"s"]
`!s2. perm_eq (filter a s ++ filter (predC a) s) s2 = perm_eq s s2`
[
((((use_arg_then2 ("perm_eqlP", [perm_eqlP]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("perm_eq_refl", [perm_eq_refl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((use_arg_then2 ("predC", [predC]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("predC", [predC]))(gsym_then (thm_tac (new_rewrite [] []))))));
(((THENL_LAST) (((fun arg_tac -> arg_tac (Arg_term (`a x`))) (disch_tac [])) THEN case THEN (simp_tac)) ((((use_arg_then2 ("cat1s", [cat1s]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("perm_catCA", [perm_catCA]))(thm_tac (new_rewrite [] [])))))) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("cat", [cat]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("perm_cons", [perm_cons]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma perm_eq_mem *)
let perm_eq_mem = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> (!x. x <- s1 <=> x <- s2)`
[
(((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["eq12"]) THEN (move ["x"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("has_pred1", [has_pred1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("has_count", [has_count]))(thm_tac (new_rewrite [] [])))))));
((((use_arg_then2 ("eq12", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma perm_eq_size *)
let perm_eq_size = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> sizel s1 = sizel s2`
[
((((use_arg_then2 ("perm_eqP", [perm_eqP]))(thm_tac (new_rewrite [] [])))) THEN (move ["eq12"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("count_predT", [count_predT]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("eq12", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma uniq_leq_size *)
let uniq_leq_size = Sections.section_proof ["s1";"s2"]
`uniq s1 ==> (!x. x <- s1 ==> x <- s2) ==> sizel s1 <= sizel s2`
[
((THENL) ((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 ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) [(((((use_arg_then2 ("size_nil", [size_nil]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq0n", [leq0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)); ((((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (move ["_"]) THEN (case THEN ((move ["Hx"]) THEN (move ["Hs1"]) THEN (move ["Hs12"]))))]);
((((fun arg_tac -> (use_arg_then2 ("Hs12", [])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (((((use_arg_then2 ("mem_head", [mem_head]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["Hxs2"])));
(((fun arg_tac -> (use_arg_then2 ("rot_to", [rot_to])) (fun fst_arg -> (use_arg_then2 ("Hxs2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN (case THEN (move ["i"])) THEN (case THEN ((move ["s2'"]) THEN (move ["Ds2'"]))));
(((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("size_rot", [size_rot])) (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 ("s2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [(`sizel s2`)]))))) THEN (((use_arg_then2 ("Ds2'", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hs1", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andTb", [andTb]))(thm_tac (new_rewrite [] []))))) THEN (move ["y"]) THEN (move ["Hy"]));
((((fun arg_tac -> (use_arg_then2 ("Hs12", [])) (fun fst_arg -> (use_arg_then2 ("y", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hy", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((fun arg_tac -> (use_arg_then2 ("mem_rot", [mem_rot])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Ds2'", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))));
((case THEN ((TRY done_tac)) THEN (move ["yx"])) THEN (((use_arg_then2 ("Hy", [])) (disch_tac [])) THEN (clear_assumption "Hy") THEN ((use_arg_then2 ("Hx", [])) (disch_tac [])) THEN (clear_assumption "Hx") THEN BETA_TAC));
(((((use_arg_then2 ("yx", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma leq_size_uniq *)
let leq_size_uniq = Sections.section_proof ["s1";"s2"]
`uniq s1 ==> (!x. x <- s1 ==> x <- s2) ==> sizel s2 <= sizel s1 ==> uniq 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) [((move ["s2"]) THEN (move ["Hs1"]) THEN (move ["Hs12"])); ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]) THEN (move ["s2"]) THEN (move ["Hs1"]) THEN (move ["Hs12"]))]);
(((THENL) (((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("nil_uniq", [nil_uniq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((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 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("Hs12", [])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN (((((use_arg_then2 ("mem_head", [mem_head]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["Hxs2"])));
(((fun arg_tac -> (use_arg_then2 ("rot_to", [rot_to])) (fun fst_arg -> (use_arg_then2 ("Hxs2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN (case THEN (move ["i"])) THEN (case THEN ((move ["s2'"]) THEN (move ["Ds2'"]))));
(((((fun arg_tac -> (use_arg_then2 ("size_rot", [size_rot])) (fun fst_arg -> (use_arg_then2 ("i", [])) (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 ("rot_uniq", [rot_uniq])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Ds2'", []))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x <- s2'`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (move ["Hs2'"])));
((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hs2'", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((fun arg_tac -> (use_arg_then2 ("size_cons", [size_cons])) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))));
(((fun arg_tac -> (use_arg_then2 ("uniq_leq_size", [uniq_leq_size])) (fun fst_arg -> (use_arg_then2 ("Hs1", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac) THEN ((move ["y"]) THEN (move ["Hy"])));
((((fun arg_tac -> (use_arg_then2 ("Hs12", [])) (fun fst_arg -> (use_arg_then2 ("Hy", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((fun arg_tac -> (use_arg_then2 ("mem_rot", [mem_rot])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Ds2'", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (case THEN ((TRY done_tac)) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("Hs1", [])) (disch_tac [])) THEN (clear_assumption "Hs1") THEN BETA_TAC) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ((move ["Hx"]) THEN (move ["Hs1"])))) THEN ((((use_arg_then2 ("Hs2'", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((fun arg_tac -> (use_arg_then2 ("IHs", [])) (fun fst_arg -> (use_arg_then2 ("Hs1", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac) THEN ((move ["y"]) THEN (move ["Hy"])));
(((fun arg_tac -> (use_arg_then2 ("Hs12", [])) (fun fst_arg -> (use_arg_then2 ("y", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun arg -> thm_tac MP_TAC arg THEN ALL_TAC)) THEN ((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hy", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((fun arg_tac -> (use_arg_then2 ("mem_rot", [mem_rot])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Ds2'", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (case THEN ((TRY done_tac)) THEN (move ["yx"])));
((((use_arg_then2 ("Hx", [])) (disch_tac [])) THEN (clear_assumption "Hx") THEN ((use_arg_then2 ("Hy", [])) (disch_tac [])) THEN (clear_assumption "Hy") THEN BETA_TAC) THEN ((((use_arg_then2 ("yx", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma uniq_size_uniq *)
let uniq_size_uniq = Sections.section_proof ["s1";"s2"]
`uniq s1 ==> (!x. x <- s1 <=> x <- s2) ==> (uniq s2 = (sizel s2 = sizel s1))`
[
(BETA_TAC THEN (move ["Us1"]) THEN (move ["Es12"]));
((((use_arg_then2 ("eqn_leq", [eqn_leq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbC", [andbC]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("uniq_leq_size", [uniq_leq_size]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("Us1", []))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("Es12", []))(thm_tac (new_rewrite [] []))))) THEN ((simp_tac THEN TRY done_tac)));
((THENL_FIRST) ((THENL) (split_tac) [(move ["Hs2"]); ALL_TAC]) (((((use_arg_then2 ("uniq_leq_size", [uniq_leq_size]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Es12", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac)));
((((use_arg_then2 ("leq_size_uniq", [leq_size_uniq])) (disch_tac [])) THEN (clear_assumption "leq_size_uniq") THEN (DISCH_THEN apply_tac)) THEN ((((use_arg_then2 ("Us1", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Es12", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma leq_size_perm *)
let leq_size_perm = Sections.section_proof ["s1";"s2"]
`uniq s1 ==> (!x. x <- s1 ==> x <- s2) ==> sizel s2 <= sizel s1 ==>
(!x. x <- s1 <=> x <- s2) /\ sizel s1 = sizel s2`
[
((BETA_TAC THEN (move ["Us1"]) THEN (move ["Hs1"]) THEN (move ["Hs12"])) THEN ((fun arg_tac -> arg_tac (Arg_term (`uniq s2`))) (term_tac (have_gen_tac [](move ["Us2"])))));
((((fun arg_tac -> (use_arg_then2 ("leq_size_uniq", [leq_size_uniq])) (fun fst_arg -> (use_arg_then2 ("Us1", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
(((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`!x. x <- s1 <=> x <- s2`))) (term_tac (have_gen_tac []ALL_TAC))));
((BETA_TAC THEN (move ["h"])) THEN ((split_tac) THEN ((TRY done_tac))) THEN (((use_arg_then2 ("uniq_size_uniq", [uniq_size_uniq]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (done_tac));
(BETA_TAC THEN (move ["x"]));
((THENL) ((THENL) (split_tac) [ALL_TAC; (move ["Hxs2"])]) [((((use_arg_then2 ("Hs1", [])) (disch_tac [])) THEN (clear_assumption "Hs1") THEN (DISCH_THEN apply_tac)) THEN (done_tac)); (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x <- s1`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN ((TRY done_tac)) THEN (move ["Hxs1"]))]);
(((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`sizel (x :: s1) <= sizel s2`))) (term_tac (have_gen_tac []ALL_TAC))));
(((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hs12", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((THENL_FIRST) ((((use_arg_then2 ("uniq_leq_size", [uniq_leq_size])) (disch_tac [])) THEN (clear_assumption "uniq_leq_size") THEN (DISCH_THEN apply_tac)) THEN ((THENL) (split_tac) [ALL_TAC; (move ["y"])])) ((((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) case [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))); (move ["Hy"])]) THEN (((use_arg_then2 ("Hs1", [])) (disch_tac [])) THEN (clear_assumption "Hs1") THEN (exact_tac)));
];;
(* Lemma perm_uniq *)
let perm_uniq = Sections.section_proof ["s1";"s2"]
`(!x. x <- s1 <=> x <- s2) ==>
sizel s1 = sizel s2 ==> uniq s1 = uniq s2`
[
((BETA_TAC THEN (move ["Es12"]) THEN (move ["Hs12"])) THEN ((split_tac) THEN (move ["Us"])));
(((((fun arg_tac -> (use_arg_then2 ("uniq_size_uniq", [uniq_size_uniq])) (fun fst_arg -> (use_arg_then2 ("Us", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("Hs12", []))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((((fun arg_tac -> (use_arg_then2 ("uniq_size_uniq", [uniq_size_uniq])) (fun fst_arg -> (use_arg_then2 ("Us", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("Hs12", []))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma perm_eq_uniq *)
let perm_eq_uniq = Sections.section_proof ["s1";"s2"]
`perm_eq s1 s2 ==> uniq s1 = uniq s2`
[
(((THENL) ((BETA_TAC THEN (move ["eq_s12"])) THEN (((use_arg_then2 ("perm_uniq", [perm_uniq])) (disch_tac [])) THEN (clear_assumption "perm_uniq") THEN (DISCH_THEN apply_tac)) THEN (split_tac)) [(((use_arg_then2 ("perm_eq_mem", [perm_eq_mem])) (disch_tac [])) THEN (clear_assumption "perm_eq_mem") THEN (exact_tac)); (((use_arg_then2 ("perm_eq_size", [perm_eq_size])) (disch_tac [])) THEN (clear_assumption "perm_eq_size") THEN (exact_tac))]) THEN (done_tac));
];;
(* Lemma uniq_perm_eq *)
let uniq_perm_eq = Sections.section_proof ["s1";"s2"]
`uniq s1 ==> uniq s2 ==>
(!x. x <- s1 <=> x <- s2) ==> perm_eq s1 s2`
[
((BETA_TAC THEN (move ["Us1"]) THEN (move ["Us2"]) THEN (move ["eq12"])) THEN (((((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 ["_"])));
(((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 ("eq12", []))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma count_mem_uniq *)
let count_mem_uniq = Sections.section_proof ["s"]
`(!x. count (pred1 x) s = if (x <- s) then 1 else 0) ==> uniq s`
[
((BETA_TAC THEN (move ["count1_s"])) THEN ((fun arg_tac -> (use_arg_then2 ("undup_uniq", [undup_uniq])) (fun fst_arg -> (use_arg_then2 ("s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun arg -> thm_tac MP_TAC arg THEN (move ["Uus"]))));
((THENL_FIRST) (((THENL_ROT 1)) ((fun arg_tac -> arg_tac (Arg_term (`perm_eq s (undup s)`))) (term_tac (have_gen_tac []ALL_TAC)))) (((DISCH_THEN (fun snd_th -> (use_arg_then2 ("perm_eq_uniq", [perm_eq_uniq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) 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 ["_"]));
(((((fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("count_uniq_mem", [count_uniq_mem])) (fun fst_arg -> (use_arg_then2 ("s", [])) (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 ("Uus", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_undup", [mem_undup]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section PermSeq *)
let perm_eqP = Sections.finalize_theorem perm_eqP;;
let perm_eq_refl = Sections.finalize_theorem perm_eq_refl;;
let perm_eq_sym = Sections.finalize_theorem perm_eq_sym;;
let perm_eq_trans = Sections.finalize_theorem perm_eq_trans;;
let perm_eqlP = Sections.finalize_theorem perm_eqlP;;
let perm_eqrP = Sections.finalize_theorem perm_eqrP;;
let perm_catC = Sections.finalize_theorem perm_catC;;
let perm_cat2l = Sections.finalize_theorem perm_cat2l;;
let perm_cons = Sections.finalize_theorem perm_cons;;
let perm_cat2r = Sections.finalize_theorem perm_cat2r;;
let perm_catAC = Sections.finalize_theorem perm_catAC;;
let perm_catCA = Sections.finalize_theorem perm_catCA;;
let perm_rcons = Sections.finalize_theorem perm_rcons;;
let perm_rot = Sections.finalize_theorem perm_rot;;
let perm_rotr = Sections.finalize_theorem perm_rotr;;
let perm_filterC = Sections.finalize_theorem perm_filterC;;
let perm_eq_mem = Sections.finalize_theorem perm_eq_mem;;
let perm_eq_size = Sections.finalize_theorem perm_eq_size;;
let uniq_leq_size = Sections.finalize_theorem uniq_leq_size;;
let leq_size_uniq = Sections.finalize_theorem leq_size_uniq;;
let uniq_size_uniq = Sections.finalize_theorem uniq_size_uniq;;
let leq_size_perm = Sections.finalize_theorem leq_size_perm;;
let perm_uniq = Sections.finalize_theorem perm_uniq;;
let perm_eq_uniq = Sections.finalize_theorem perm_eq_uniq;;
let uniq_perm_eq = Sections.finalize_theorem uniq_perm_eq;;
let count_mem_uniq = Sections.finalize_theorem count_mem_uniq;;
Sections.end_section "PermSeq";;
(* Section RotrLemmas *)
Sections.begin_section "RotrLemmas";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(* Lemma size_rotr *)
let size_rotr = Sections.section_proof ["s"]
`sizel (rotr n0 s) = sizel s`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mem_rotr *)
let mem_rotr = Sections.section_proof ["s"]
`!x. x <- rotr n0 s <=> x <- s`
[
((BETA_TAC THEN (move ["x"])) THEN ((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mem_rot", [mem_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr_size_cat *)
let rotr_size_cat = Sections.section_proof ["s1";"s2"]
`rotr (sizel s2) (s1 ++ s2) = s2 ++ s1`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addnK", [addnK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr1_rcons *)
let rotr1_rcons = Sections.section_proof ["x";"s"]
`rotr 1 (rcons s x) = x :: s`
[
(((((use_arg_then2 ("rot1_cons", [rot1_cons]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rotK", [rotK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_rotr *)
let has_rotr = Sections.section_proof ["a";"s"]
`has a (rotr n0 s) = has a s`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("has_rot", [has_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr_uniq *)
let rotr_uniq = Sections.section_proof ["s"]
`uniq (rotr n0 s) = uniq s`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_uniq", [rot_uniq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotrK *)
let rotrK = Sections.section_proof []
`!s. rot n0 (rotr n0 s) = s`
[
(BETA_TAC THEN (move ["s"]));
((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltnP", [ltnP])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun arg -> thm_tac MP_TAC arg THEN ((THENL) case [(move ["lt_n0s"]); (move ["ge_n0s"])])));
(((((fun arg_tac -> (use_arg_then2 ("subKn", [subKn])) (fun fst_arg -> (fun arg_tac -> (use_arg_then2 ("ltnW", [ltnW])) (fun fst_arg -> (use_arg_then2 ("lt_n0s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("size_rotr", [size_rotr]))(gsym_then (thm_tac (new_rewrite [1] [(`sizel s`)]))))) THEN (((use_arg_then2 ("rotr", [rotr]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [(`rotr n0 _`)])))) THEN (((use_arg_then2 ("rotK", [rotK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((fun arg_tac -> (use_arg_then2 ("rot_oversize", [rot_oversize])) (fun fst_arg -> (use_arg_then2 ("ge_n0s", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [2] []))))) THEN (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("subn_eq0", [subn_eq0])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("ge_n0s", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("rot0", [rot0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rotr_inj *)
let rotr_inj = Sections.section_proof ["s1";"s2"]
`rotr n0 (s1:(A)list) = rotr n0 s2 ==> s1 = s2`
[
(BETA_TAC THEN (move ["h"]));
(((((use_arg_then2 ("rotrK", [rotrK]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("h", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rotrK", [rotrK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rev_rot *)
let rev_rot = Sections.section_proof ["s"]
`rev (rot n0 s) = rotr n0 (rev s)`
[
((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rev", [size_rev]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (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 [3] [(`s`)]))))) THEN (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("rev_cat", [rev_cat]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("size_drop", [size_drop]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_rev", [size_rev]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma rev_rotr *)
let rev_rotr = Sections.section_proof ["s"]
`rev (rotr n0 s) = rot n0 (rev s)`
[
(((((use_arg_then2 ("rotrK", [rotrK]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rotrK", [rotrK]))(gsym_then (thm_tac (new_rewrite [] [(`rot n0 (rev s)`)])))))) THEN (AP_TERM_TAC) THEN (((use_arg_then2 ("rotK", [rotK]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rev", [size_rev]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_rotr", [size_rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [(`rot _ s`)])))) THEN (((use_arg_then2 ("rev_cat", [rev_cat]))(thm_tac (new_rewrite [] [])))));
((fun arg_tac -> arg_tac (Arg_term (`sizel s - n0`))) (term_tac (set_tac "m")));
((THENL_ROT (-1)) (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("size_takel", [size_takel])) (fun fst_arg -> (use_arg_then2 ("m", [])) (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] []))))));
(((((use_arg_then2 ("size_rev", [size_rev]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rev_cat", [rev_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("m_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leq_subr", [leq_subr]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section RotrLemmas *)
let size_rotr = Sections.finalize_theorem size_rotr;;
let mem_rotr = Sections.finalize_theorem mem_rotr;;
let rotr_size_cat = Sections.finalize_theorem rotr_size_cat;;
let rotr1_rcons = Sections.finalize_theorem rotr1_rcons;;
let has_rotr = Sections.finalize_theorem has_rotr;;
let rotr_uniq = Sections.finalize_theorem rotr_uniq;;
let rotrK = Sections.finalize_theorem rotrK;;
let rotr_inj = Sections.finalize_theorem rotr_inj;;
let rev_rot = Sections.finalize_theorem rev_rot;;
let rev_rotr = Sections.finalize_theorem rev_rotr;;
Sections.end_section "RotrLemmas";;
(* Section RotCompLemmas *)
Sections.begin_section "RotCompLemmas";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(* Lemma rot_addn *)
let rot_addn = Sections.section_proof ["m";"n";"s"]
`m + n <= sizel s ==> rot (m + n) s = rot m (rot n s)`
[
((BETA_TAC THEN (move ["sz_s"])) THEN ((((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] [])))) THEN (((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)))(gsym_then (thm_tac (new_rewrite [] [(`take _ s`)])))))));
((((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_takel", [size_takel]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("leq_addl", [leq_addl]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("addnK", [addnK]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rotS *)
let rotS = Sections.section_proof ["n";"s"]
`n < sizel s ==> rot (SUC n) s = rot 1 (rot n s)`
[
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add1n", [add1n]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("rot_addn", [rot_addn])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (done_tac));
];;
(* Lemma rot_add_mod *)
let rot_add_mod = Sections.section_proof ["m";"n";"s"]
`n <= sizel s ==> m <= sizel s ==>
rot m (rot n s) = rot (if m + n <= sizel s then m + n else (m + n) - sizel s) s`
[
((THENL) ((BETA_TAC THEN (move ["Hn"]) THEN (move ["Hm"])) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`m + n <= sizel s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac))) [((DISCH_THEN (fun snd_th -> (use_arg_then2 ("rot_addn", [rot_addn])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))); BETA_TAC]);
(((((use_arg_then2 ("ltnNge", [ltnNge]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("ltnW", [ltnW])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (move ["Hmn"])) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))));
(((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("rotK", [rotK])) (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 [2] [(`s`)]))))) THEN (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_addn", [rot_addn]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn_subA", [addn_subA]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("subnK", [subnK]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("addnK", [addnK]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rot_rot *)
let rot_rot = Sections.section_proof ["m";"n";"s"]
`rot m (rot n s) = rot n (rot m s)`
[
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltnP", [ltnP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("m", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (move ["Hm"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [(`rot m _`)]))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 1 (((use_arg_then2 ("ltnW", [ltnW]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("ltnP", [ltnP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`sizel s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("n", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (move ["Hn"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("rot_oversize", [rot_oversize]))(thm_tac (new_rewrite [] [(`rot n _`)]))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 1 (((use_arg_then2 ("ltnW", [ltnW]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((repeat_tactic 1 9 (((use_arg_then2 ("rot_add_mod", [rot_add_mod]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 1 (((use_arg_then2 ("addnC", [addnC]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rot_rotr *)
let rot_rotr = Sections.section_proof ["m";"n";"s"]
`rot m (rotr n s) = rotr n (rot m s)`
[
(((((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] [(`rotr n (rot m s)`)])))) THEN (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rot_rot", [rot_rot]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rotr", [rotr]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma rotr_rotr *)
let rotr_rotr = Sections.section_proof ["m";"n";"s"]
`rotr m (rotr n s) = rotr n (rotr m s)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("rotr", [rotr]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_rot", [size_rot]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rot_rot", [rot_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section RotCompLemmas *)
let rot_addn = Sections.finalize_theorem rot_addn;;
let rotS = Sections.finalize_theorem rotS;;
let rot_add_mod = Sections.finalize_theorem rot_add_mod;;
let rot_rot = Sections.finalize_theorem rot_rot;;
let rot_rotr = Sections.finalize_theorem rot_rotr;;
let rotr_rotr = Sections.finalize_theorem rotr_rotr;;
Sections.end_section "RotCompLemmas";;
(* Section Mask *)
Sections.begin_section "Mask";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_type (mk_var ("m", (`:(bool)list`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("s1", (`:(A)list`))));;
let mask = define `mask [] s' = [] /\ mask m' [] = [] /\
mask (b :: m') (x :: s') = if b then x :: mask m' s' else mask m' s'`;;
(* Lemma mask_false *)
let mask_false = Sections.section_proof ["s";"n"]
`mask (nseq n F) 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("nseq", [nseq]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
(* Lemma mask_true *)
let mask_true = Sections.section_proof ["s";"n"]
`sizel s <= n ==> mask (nseq n T) s = 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(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 (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mask0 *)
let mask0 = Sections.section_proof ["m"]
`mask m [] = []`
[
(((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN elim) [ALL_TAC; ((move ["m"]) THEN (move ["_"]))]) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma mask1 *)
let mask1 = Sections.section_proof ["b";"x"]
`mask [b] [x] = nseq (if b then 1 else 0) x`
[
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case THEN (simp_tac)) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ONE", [ONE]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma mask_cons *)
let mask_cons = Sections.section_proof ["b";"m";"x";"s"]
`mask (b :: m) (x :: s) = nseq (if b then 1 else 0) x ++ mask m s`
[
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ONE", [ONE]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("cat1s", [cat1s]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_mask *)
let size_mask = Sections.section_proof ["m";"s"]
`sizel m = sizel s ==> sizel (mask m s) = count I m`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN elim) [ALL_TAC; ((move ["b"]) THEN (move ["m"]) THEN (move ["IHm"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("eqS0", [eqS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("eqSS", [eqSS]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("I_THM", [I_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case THEN (simp_tac) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHm", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (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 ("add1n", [add1n]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mask_cat *)
let mask_cat = Sections.section_proof ["m1";"s1";"m2";"s2"]
`sizel m1 = sizel s1 ==>
mask (m1 ++ m2) (s1 ++ s2) = mask m1 s1 ++ mask m2 s2`
[
(BETA_TAC THEN (move ["Hm1"]));
(((THENL) (((use_arg_then2 ("Hm1", [])) (disch_tac [])) THEN (clear_assumption "Hm1") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN ((use_arg_then2 ("m1", [])) (disch_tac [])) THEN (clear_assumption "m1") THEN elim) [ALL_TAC; ((move ["b1"]) THEN (move ["m1"]) THEN (move ["IHm"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x1"]) THEN (move ["s1"]) THEN (move ["_"]))]) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("mask0", [mask0]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) 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 [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`0 = _`)]))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHm", [])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("b1", [])) (disch_tac [])) THEN (clear_assumption "b1") THEN case THEN (simp_tac)) THEN (((use_arg_then2 ("cat_cons", [cat_cons]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma has_mask_cons *)
let has_mask_cons = Sections.section_proof ["a";"b";"m";"x";"s"]
`has a (mask (b :: m) (x :: s)) <=> b /\ a x \/ has a (mask m s)`
[
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma mask_rot *)
let mask_rot = Sections.section_proof ["m";"s"]
`sizel m = sizel s ==>
mask (rot n0 m) (rot n0 s) = rot (count I (take n0 m)) (mask m s)`
[
(BETA_TAC THEN (move ["Hs"]));
((THENL_FIRST) ((fun arg_tac -> arg_tac (Arg_term (`sizel (take n0 m) = sizel (take n0 s)`))) (term_tac (have_gen_tac [](move ["Hsn0"])))) (((repeat_tactic 1 9 (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Hs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((((fun arg_tac -> (use_arg_then2 ("size_mask", [size_mask])) (fun fst_arg -> (use_arg_then2 ("Hsn0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 2 0 (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mask_cat", [mask_cat]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("Hs", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("m", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [4] [(`m`)]))))) THEN (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (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 [4] [(`s`)]))))) THEN (((use_arg_then2 ("mask_cat", [mask_cat]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((use_arg_then2 ("rot_size_cat", [rot_size_cat]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section Mask *)
let mask_false = Sections.finalize_theorem mask_false;;
let mask_true = Sections.finalize_theorem mask_true;;
let mask0 = Sections.finalize_theorem mask0;;
let mask1 = Sections.finalize_theorem mask1;;
let mask_cons = Sections.finalize_theorem mask_cons;;
let size_mask = Sections.finalize_theorem size_mask;;
let mask_cat = Sections.finalize_theorem mask_cat;;
let has_mask_cons = Sections.finalize_theorem has_mask_cons;;
let mask_rot = Sections.finalize_theorem mask_rot;;
Sections.end_section "Mask";;
(* Section EqMask *)
Sections.begin_section "EqMask";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(Sections.add_section_type (mk_var ("m", (`:(bool)list`))));;
(* Lemma mem_mask_cons *)
let mem_mask_cons = Sections.section_proof ["x";"b";"m";"y";"s"]
`(x <- mask (b :: m) (y :: s)) <=> b /\ (x = y) \/ (x <- mask m s)`
[
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("in_cons", [in_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma mem_mask *)
let mem_mask = Sections.section_proof ["x";"m";"s"]
`x <- mask m s ==> x <- s`
[
(((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["p"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["m"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
((((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN case THEN (simp_tac)) THEN (repeat_tactic 0 10 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> arg_tac (Arg_term (`x = y`))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Lemma mask_uniq *)
let mask_uniq = Sections.section_proof ["s"]
`uniq s ==> !m. uniq (mask m s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((repeat_tactic 0 10 (((use_arg_then2 ("mask0", [mask0]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("nil_uniq", [nil_uniq]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("cons_uniq", [cons_uniq]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN ((move ["Hx"]) THEN (move ["Hs"])))) THEN ((THENL) elim [ALL_TAC; ((move ["b"]) THEN (move ["m"]) THEN (move ["_"]))]));
(((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nil_uniq", [nil_uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("b", [])) (disch_tac [])) THEN (clear_assumption "b") THEN case) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("IHs", [])) (fun fst_arg -> (use_arg_then2 ("Hs", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("m", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac))));
((((use_arg_then2 ("Hx", [])) (disch_tac [])) THEN (clear_assumption "Hx") THEN BETA_TAC) 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_mask", [mem_mask])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (done_tac));
];;
(* Lemma mem_mask_rot *)
let mem_mask_rot = Sections.section_proof ["m";"s"]
`sizel m = sizel s ==>
(!x. x <- mask (rot n0 m) (rot n0 s) <=> x <- mask m s)`
[
((BETA_TAC THEN (move ["Hm"]) THEN (move ["x"])) THEN ((((use_arg_then2 ("mask_rot", [mask_rot]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mem_rot", [mem_rot]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section EqMask *)
let mem_mask_cons = Sections.finalize_theorem mem_mask_cons;;
let mem_mask = Sections.finalize_theorem mem_mask;;
let mask_uniq = Sections.finalize_theorem mask_uniq;;
let mem_mask_rot = Sections.finalize_theorem mem_mask_rot;;
Sections.end_section "EqMask";;
(* Section Subseq *)
Sections.begin_section "Subseq";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("s1", (`:(A)list`))));;
(* Lemma sub0seq *)
let sub0seq = Sections.section_proof ["s"]
`subseq [] s`
[
((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma subseq0 *)
let subseq0 = Sections.section_proof ["s"]
`subseq s [] = (s = [])`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
(* Lemma subseqP *)
let subseqP = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 <=> (?m. sizel m = sizel s2 /\ s1 = mask m s2)`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN ((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s2"]) THEN (move ["IHs2"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((fun arg_tac -> arg_tac (Arg_term (`[]:(bool)list`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
(((((use_arg_then2 ("NOT_EXISTS_THM", [NOT_EXISTS_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mask0", [mask0]))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
(((fun arg_tac -> arg_tac (Arg_term (`nseq (SUC (sizel s2)) F`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("size_nseq", [size_nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mask_false", [mask_false]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("IHs2", []))(thm_tac (new_rewrite [] [])))) THEN ((split_tac) THEN ALL_TAC THEN (case THEN (move ["n"])) THEN (case THEN ((move ["sz_m"]) THEN (move ["def_s1"])))) THEN (((use_arg_then2 ("IHs2", [])) (disch_tac [])) THEN (clear_assumption "IHs2") THEN BETA_TAC THEN (move ["_"])));
(((fun arg_tac -> arg_tac (Arg_term (`(x = y) :: n`))) (term_tac exists_tac)) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((((use_arg_then2 ("def_s1", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (simp_tac)));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (done_tac));
((THENL_ROT (-1)) ((THENL) (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) [(BETA_TAC THEN (move ["_"])); (BETA_TAC THEN (move ["ne_xy"]))]));
(((THENL) (((use_arg_then2 ("sz_m", [])) (disch_tac [])) THEN (clear_assumption "sz_m") THEN ((use_arg_then2 ("def_s1", [])) (disch_tac [])) THEN (clear_assumption "def_s1") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN case) [ALL_TAC; ((case THEN ALL_TAC) THEN (move ["m"]))]) THEN (((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (move ["eq"]) THEN (move ["seq"])));
((((use_arg_then2 ("eq", [])) (disch_tac [])) THEN (clear_assumption "eq") THEN BETA_TAC) THEN ((((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (done_tac));
(((use_arg_then2 ("m", [])) (term_tac exists_tac)) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`indexl T n`))) (term_tac (set_tac "i")));
((fun arg_tac -> arg_tac (Arg_term (`take i n = nseq (sizel (take i n)) F`))) (term_tac (have_gen_tac [](move ["def_m_i"]))));
(((((use_arg_then2 ("all_pred1P", [all_pred1P]))(thm_tac (new_rewrite [] [])))) THEN (((fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("all_nthP", [all_nthP])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`pred1 F`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`take i n`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`T`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (move ["j"]));
(((((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("minn", [minn]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leq_minl", [leq_minl]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_or", [negb_or]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (case THEN (move ["lt_j_i"]) THEN (move ["_"])));
((((fun arg_tac -> (use_arg_then2 ("nth_take", [nth_take])) (fun fst_arg -> (use_arg_then2 ("lt_j_i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt_j_i", [])) (disch_tac [])) THEN (clear_assumption "lt_j_i") THEN BETA_TAC) THEN (((((use_arg_then2 ("i_def", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("before_find", [before_find])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN ((fun arg_tac -> (conv_thm_tac DISCH_THEN) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`T`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac MP_TAC))));
(((repeat_tactic 1 9 (((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] []))))) THEN (simp_tac)) THEN (done_tac));
((fun arg_tac -> arg_tac (Arg_term (`i < sizel n`))) (term_tac (have_gen_tac [](move ["lt_i_m"]))));
((((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN ((((fun arg_tac -> arg_tac (Arg_theorem (TAUT `!P. (P ==> F) <=> ~P`)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (move ["le_m_i"])));
((((use_arg_then2 ("def_s1", [])) (disch_tac [])) THEN (clear_assumption "def_s1") THEN ((use_arg_then2 ("def_m_i", [])) (disch_tac [])) THEN (clear_assumption "def_m_i") THEN BETA_TAC) THEN (((((use_arg_then2 ("take_oversize", [take_oversize]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mask_false", [mask_false]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("def_m_i", [])) (disch_tac [])) THEN (clear_assumption "def_m_i") THEN BETA_TAC) THEN (((((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt_i_m", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["def_m_i"])));
(((fun arg_tac -> arg_tac (Arg_term (`take i n ++ dropl (SUC i) n`))) (term_tac exists_tac)) THEN (split_tac));
((((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_take", [size_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("lt_i_m", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
((((use_arg_then2 ("lt_i_m", [])) (disch_tac [])) THEN (clear_assumption "lt_i_m") THEN BETA_TAC) THEN (((((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("subnKC", [subnKC])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN ((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addSn", [addSn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("congr1", [congr1])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`behead`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("def_s1", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC) THEN ((((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))));
((((fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] [(`s2`)]))))) THEN (((fun arg_tac -> (use_arg_then2 ("cat_take_drop", [cat_take_drop])) (fun fst_arg -> (use_arg_then2 ("i", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [1] [(`n`)]))))) THEN (((use_arg_then2 ("def_m_i", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_cons", [cat_cons]))(gsym_then (thm_tac (new_rewrite [] []))))));
((fun arg_tac -> arg_tac (Arg_term (`sizel (take i s2) = i`))) (term_tac (have_gen_tac [](move ["sz_i_s2"]))));
((((use_arg_then2 ("size_takel", [size_takel])) (disch_tac [])) THEN (clear_assumption "size_takel") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("lt_i_m", [])) (disch_tac [])) THEN (clear_assumption "lt_i_m") THEN BETA_TAC) THEN ((((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("lastI", [lastI]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat_rcons", [cat_rcons]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("mask_cat", [mask_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_nseq", [size_nseq]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_belast", [size_belast]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mask_false", [mask_false]))(thm_tac (new_rewrite [] []))))) THEN ((simp_tac THEN TRY done_tac)) THEN (repeat_tactic 1 9 (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] []))))));
((((fun arg_tac -> (use_arg_then2 ("drop_nth", [drop_nth])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`T`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("i_def", []))(gsym_then (thm_tac (new_rewrite [1] []))))) THEN (((use_arg_then2 ("nth_index", [nth_index]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("index_mem", [index_mem]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("i_def", []))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)));
(((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma subseq_trans *)
let subseq_trans = Sections.section_proof ["s1";"s2";"s3"]
`subseq s1 s2 ==> subseq s2 s3 ==> subseq s1 s3`
[
(((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m2"])) THEN (case THEN ((move ["_"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) THEN ((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m1"])) THEN (case THEN ((move ["_"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("m1", [])) (disch_tac [])) THEN (clear_assumption "m1") THEN ((use_arg_then2 ("m2", [])) (disch_tac [])) THEN (clear_assumption "m2") THEN ((use_arg_then2 ("s3", [])) (disch_tac [])) THEN (clear_assumption "s3") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) (((repeat_tactic 1 9 (((use_arg_then2 ("mask0", [mask0]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subseq0", [subseq0]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
(BETA_TAC THEN (move ["m2"]) THEN (move ["m1"]));
(((THENL) (((use_arg_then2 ("m1", [])) (disch_tac [])) THEN (clear_assumption "m1") THEN case) [ALL_TAC; ((case THEN ALL_TAC) THEN (move ["m1"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mask0", [mask0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((THENL) (((use_arg_then2 ("m2", [])) (disch_tac [])) THEN (clear_assumption "m2") THEN case) [ALL_TAC; ((case THEN ALL_TAC) THEN (move ["m2"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("IHs", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("IHs", [])) (fun fst_arg -> (use_arg_then2 ("m2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("m1", [])) (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 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["sz_m"]) THEN (move ["def_s"])))));
(((fun arg_tac -> arg_tac (Arg_term (`F :: m`))) (term_tac exists_tac)) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("def_s", []))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("IHs", [])) (fun fst_arg -> (use_arg_then2 ("m2", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("m1", [])) (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 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["sz_m"]) THEN (move ["def_s"])))));
(((fun arg_tac -> arg_tac (Arg_term (`F :: m`))) (term_tac exists_tac)) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("def_s", []))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma subseq_refl *)
let subseq_refl = Sections.section_proof ["s"]
`subseq s s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma subseq_cat *)
let subseq_cat = Sections.section_proof ["s1";"s2";"s3";"s4"]
`subseq s1 s3 ==> subseq s2 s4 ==> subseq (s1 ++ s2) (s3 ++ s4)`
[
((repeat_tactic 1 9 (((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["m1"])) THEN (case THEN ((move ["sz_m1"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))) THEN (case THEN (move ["m2"])) THEN (case THEN ((move ["sz_m2"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))));
(((fun arg_tac -> arg_tac (Arg_term (`m1 ++ m2`))) (term_tac exists_tac)) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("mask_cat", [mask_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("sz_m1", []))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("sz_m2", []))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma mem_subseq *)
let mem_subseq = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> (!x. x <- s1 ==> x <- s2)`
[
(((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["_"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))) THEN (move ["x"])) THEN (((use_arg_then2 ("mem_mask", [mem_mask])) (disch_tac [])) THEN (clear_assumption "mem_mask") THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Lemma subseq_seq1 *)
let subseq_seq1 = Sections.section_proof ["x";"s"]
`subseq [x] s <=> x <- s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("MEM", [MEM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
((((fun arg_tac -> (use_arg_then2 ("orbN", [orbN])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma size_subseq *)
let size_subseq = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> sizel s1 <= sizel s2`
[
((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["sz_m"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))));
(((((use_arg_then2 ("size_mask", [size_mask]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("sz_m", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("count_size", [count_size]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma size_subseq_leqif *)
let size_subseq_leqif = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> leqif (sizel s1) (sizel s2) (s1 = s2)`
[
((THENL_FIRST) ((BETA_TAC THEN (move ["sub12"])) THEN (((use_arg_then2 ("leqif", [leqif]))(thm_tac (new_rewrite [] [])))) THEN (split_tac)) (((use_arg_then2 ("size_subseq", [size_subseq])) (disch_tac [])) THEN (clear_assumption "size_subseq") THEN (exact_tac)));
(((THENL) (split_tac) [ALL_TAC; ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)))]) THEN (((use_arg_then2 ("sub12", [])) (disch_tac [])) THEN (clear_assumption "sub12") THEN BETA_TAC) THEN ((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["sz_m"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))));
((((use_arg_then2 ("size_mask", [size_mask]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("sz_m", []))(gsym_then (thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("all_count", [all_count]))(gsym_then (thm_tac (new_rewrite [] []))))));
((fun arg_tac -> arg_tac (Arg_term (`all I m = all (pred1 T) m`))) (term_tac (have_gen_tac [](((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))));
(((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("eq_all", [eq_all])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`I:bool->bool`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`pred1 T`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN BETA_TAC);
(((((use_arg_then2 ("pred1", [pred1]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("I_THM", [I_THM]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (done_tac));
(((((use_arg_then2 ("all_pred1P", [all_pred1P]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("sz_m", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mask_true", [mask_true]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("leqnn", [leqnn]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma subseq_cons *)
let subseq_cons = Sections.section_proof ["s";"x"]
`subseq s (x :: s)`
[
(((fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("subseq_cat", [subseq_cat])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`[]`))) (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))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`[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);
(((((use_arg_then2 ("subseq_refl", [subseq_refl]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cat1s", [cat1s]))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Lemma subseq_rcons *)
let subseq_rcons = Sections.section_proof ["s";"x"]
`subseq s (rcons s x)`
[
(((((use_arg_then2 ("cats0", [cats0]))(gsym_then (thm_tac (new_rewrite [1] [(`s`)]))))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("subseq_cat", [subseq_cat]))(thm_tac (new_rewrite [] []))))) THEN ((((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("subseq_refl", [subseq_refl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
(* Lemma subseq_uniq *)
let subseq_uniq = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> uniq s2 ==> uniq s1`
[
(((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["_"]) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))) THEN (move ["Us2"])) THEN (((use_arg_then2 ("mask_uniq", [mask_uniq]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section Subseq *)
let sub0seq = Sections.finalize_theorem sub0seq;;
let subseq0 = Sections.finalize_theorem subseq0;;
let subseqP = Sections.finalize_theorem subseqP;;
let subseq_trans = Sections.finalize_theorem subseq_trans;;
let subseq_refl = Sections.finalize_theorem subseq_refl;;
let subseq_cat = Sections.finalize_theorem subseq_cat;;
let mem_subseq = Sections.finalize_theorem mem_subseq;;
let subseq_seq1 = Sections.finalize_theorem subseq_seq1;;
let size_subseq = Sections.finalize_theorem size_subseq;;
let size_subseq_leqif = Sections.finalize_theorem size_subseq_leqif;;
let subseq_cons = Sections.finalize_theorem subseq_cons;;
let subseq_rcons = Sections.finalize_theorem subseq_rcons;;
let subseq_uniq = Sections.finalize_theorem subseq_uniq;;
Sections.end_section "Subseq";;
(* Section Map *)
Sections.begin_section "Map";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_var (mk_var ("x1", (`:A`))));;
(Sections.add_section_var (mk_var ("x2", (`:B`))));;
(Sections.add_section_var (mk_var ("f", (`:A -> B`))));;
(* Lemma map_MAP *)
let map_MAP = Sections.section_proof []
`map = MAP`
[
((((use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac apply_tac)) THEN (move ["f"])) THEN (((use_arg_then2 ("EQ_EXT", [EQ_EXT])) (thm_tac apply_tac)) THEN (move ["s"])));
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("MAP", [MAP]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma map_cons *)
let map_cons = Sections.section_proof ["x";"s"]
`map f (x :: s) = f x :: map f s`
[
((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma map_nseq *)
let map_nseq = Sections.section_proof ["x"]
`map f (nseq n0 x) = nseq n0 (f x)`
[
(((THENL) (((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("nseq", [nseq]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))));
((((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma map_cat *)
let map_cat = Sections.section_proof ["s1";"s2"]
`map f (s1 ++ s2) = map f s1 ++ map f s2`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (done_tac));
];;
(* Lemma size_map *)
let size_map = Sections.section_proof ["s"]
`sizel (map f s) = sizel s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma behead_map *)
let behead_map = Sections.section_proof ["s"]
`behead (map f s) = map f (behead s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("behead", [behead]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_map *)
let nth_map = Sections.section_proof ["n";"s"]
`n < sizel s ==> nth x2 (map f s) n = f (nth x1 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (done_tac));
];;
(* Lemma map_rcons *)
let map_rcons = Sections.section_proof ["s";"x"]
`map f (rcons s x) = rcons (map f s) (f x)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("map_cat", [map_cat]))(thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma last_map *)
let last_map = Sections.section_proof ["s";"x"]
`last (f x) (map f s) = f (last x 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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma belast_map *)
let belast_map = Sections.section_proof ["s";"x"]
`belast (f x) (map f s) = map f (belast x 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]) THEN (move ["x"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("belast", [belast]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (done_tac));
];;
(* Lemma filter_map *)
let filter_map = Sections.section_proof ["a";"s"]
`filter a (map f s) = map f (filter (preim f a) s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("preim", [preim]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a (f x)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["_"])) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (done_tac));
];;
(* Lemma find_map *)
let find_map = Sections.section_proof ["a";"s"]
`find a (map f s) = find (preim f a) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("preim", [preim]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma has_map *)
let has_map = Sections.section_proof ["a";"s"]
`has a (map f s) = has (preim f a) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("has", [has]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("preim", [preim]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma all_map *)
let all_map = Sections.section_proof ["a";"s"]
`all a (map f s) = all (preim f a) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("preim", [preim]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma count_map *)
let count_map = Sections.section_proof ["a";"s"]
`count a (map f s) = count (preim f a) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("count", [count]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("preim", [preim]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_take *)
let map_take = Sections.section_proof ["s"]
`map f (take n0 s) = take n0 (map f s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma map_drop *)
let map_drop = Sections.section_proof ["s"]
`map f (dropl n0 s) = dropl n0 (map f s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("n0", [])) (disch_tac [])) THEN (clear_assumption "n0") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("drop", [drop]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma map_rot *)
let map_rot = Sections.section_proof ["s"]
`map f (rot n0 s) = rot n0 (map f s)`
[
(((repeat_tactic 1 9 (((use_arg_then2 ("rot", [rot]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("map_cat", [map_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map_take", [map_take]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map_drop", [map_drop]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_rotr *)
let map_rotr = Sections.section_proof ["s"]
`map f (rotr n0 s) = rotr n0 (map f s)`
[
(((fun arg_tac -> (use_arg_then2 ("rot_inj", [rot_inj])) (fun fst_arg -> (use_arg_then2 ("n0", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac apply_tac)) THEN ((((use_arg_then2 ("rotrK", [rotrK]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map_rot", [map_rot]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("rotrK", [rotrK]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_rev *)
let map_rev = Sections.section_proof ["s"]
`map f (rev s) = rev (map f s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rev_cons", [rev_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map_rcons", [map_rcons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma map_mask *)
let map_mask = Sections.section_proof ["m";"s"]
`map f (mask m s) = mask m (map f s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN elim) [ALL_TAC; ((case THEN ALL_TAC) THEN (move ["m"]) THEN (move ["IHm"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["p"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("map_cons", [map_cons]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("IHm", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma inj_map *)
let inj_map = Sections.section_proof []
`(!x y. f x = f y ==> x = y) ==> (!s1 s2. map f s1 = map f s2 ==> s1 = s2)`
[
((BETA_TAC THEN (move ["injf"])) THEN ((THENL) elim [ALL_TAC; ((move ["y1"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y2"]) THEN (move ["s2"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`[] = CONS _1 _2`)]))))) THEN ((((use_arg_then2 ("NOT_CONS_NIL", [NOT_CONS_NIL]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("eqseq_cons", [eqseq_cons]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("injf", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) THEN (done_tac));
];;
(* Finalization of the section Map *)
let map_MAP = Sections.finalize_theorem map_MAP;;
let map_cons = Sections.finalize_theorem map_cons;;
let map_nseq = Sections.finalize_theorem map_nseq;;
let map_cat = Sections.finalize_theorem map_cat;;
let size_map = Sections.finalize_theorem size_map;;
let behead_map = Sections.finalize_theorem behead_map;;
let nth_map = Sections.finalize_theorem nth_map;;
let map_rcons = Sections.finalize_theorem map_rcons;;
let last_map = Sections.finalize_theorem last_map;;
let belast_map = Sections.finalize_theorem belast_map;;
let filter_map = Sections.finalize_theorem filter_map;;
let find_map = Sections.finalize_theorem find_map;;
let has_map = Sections.finalize_theorem has_map;;
let all_map = Sections.finalize_theorem all_map;;
let count_map = Sections.finalize_theorem count_map;;
let map_take = Sections.finalize_theorem map_take;;
let map_drop = Sections.finalize_theorem map_drop;;
let map_rot = Sections.finalize_theorem map_rot;;
let map_rotr = Sections.finalize_theorem map_rotr;;
let map_rev = Sections.finalize_theorem map_rev;;
let map_mask = Sections.finalize_theorem map_mask;;
let inj_map = Sections.finalize_theorem inj_map;;
Sections.end_section "Map";;
(* Lemma filter_mask *)
let filter_mask = Sections.section_proof ["a";"s"]
`filter (a:A->bool) s = mask (map a s) s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac)) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN ((((use_arg_then2 ("mask", [mask]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)) THEN (done_tac));
];;
(* Section FilterSubseq *)
Sections.begin_section "FilterSubseq";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))); Sections.add_section_type (mk_var ("s1", (`:(A)list`))));;
(Sections.add_section_type (mk_var ("a", (`:A -> bool`))));;
(* Lemma filter_subseq *)
let filter_subseq = Sections.section_proof ["a";"s"]
`subseq (filter a s) s`
[
((((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] [])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`map a s`))) (term_tac exists_tac)) THEN ((((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("filter_mask", [filter_mask]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma subseq_filter *)
let subseq_filter = Sections.section_proof ["s1";"s2";"a"]
`subseq s1 (filter a s2) <=> all a s1 /\ subseq s1 s2`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN ((use_arg_then2 ("s2", [])) (disch_tac [])) THEN (clear_assumption "s2") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s2"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("filter", [filter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("all", [all]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
((((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`a x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["ax"])) THEN (((use_arg_then2 ("subseq", [subseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`y = x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["yx"])) THEN ((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("all_cons", [all_cons]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma subseq_uniqP *)
let subseq_uniqP = Sections.section_proof ["s1";"s2"]
`uniq s2 ==> (subseq s1 s2 <=> s1 = filter (\x. x <- s1) s2)`
[
((THENL_LAST) ((BETA_TAC THEN (move ["uniq_s2"])) THEN ((THENL) (split_tac) [(move ["ss12"]); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))])) ((((use_arg_then2 ("filter_subseq", [filter_subseq]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
((fun arg_tac -> arg_tac (Arg_term (`subseq s1 (filter (\x. x <- s1) s2)`))) (term_tac (have_gen_tac []ALL_TAC)));
(((((use_arg_then2 ("subseq_filter", [subseq_filter]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("allP", [allP]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("size_subseq_leqif", [size_subseq_leqif])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC) THEN ((DISCH_THEN (fun snd_th -> (use_arg_then2 ("leqif_imp_eq", [leqif_imp_eq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))));
((((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("perm_eq_size", [perm_eq_size])) (disch_tac [])) THEN (clear_assumption "perm_eq_size") THEN (DISCH_THEN apply_tac)));
((((use_arg_then2 ("uniq_perm_eq", [uniq_perm_eq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("filter_uniq", [filter_uniq]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("subseq_uniq", [subseq_uniq])) (fun fst_arg -> (use_arg_then2 ("ss12", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)));
((((((use_arg_then2 ("mem_filter", [mem_filter]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["x"])) THEN ((((use_arg_then2 ("andb_idr", [andb_idr]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (((fun arg_tac -> (use_arg_then2 ("mem_subseq", [mem_subseq])) (fun fst_arg -> (use_arg_then2 ("ss12", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Finalization of the section FilterSubseq *)
let filter_subseq = Sections.finalize_theorem filter_subseq;;
let subseq_filter = Sections.finalize_theorem subseq_filter;;
let subseq_uniqP = Sections.finalize_theorem subseq_uniqP;;
Sections.end_section "FilterSubseq";;
(* Section EqMap *)
Sections.begin_section "EqMap";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_var (mk_var ("x1", (`:A`))));;
(Sections.add_section_var (mk_var ("x2", (`:B`))));;
(Sections.add_section_var (mk_var ("f", (`:A -> B`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(* Lemma map_f *)
let map_f = Sections.section_proof ["s";"x"]
`x <- s ==> f x <- map f s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((THENL) case [((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))); (move ["Hx"])]) THEN (DISJ2_TAC) THEN (((use_arg_then2 ("IHs", [])) (disch_tac [])) THEN (clear_assumption "IHs") THEN (DISCH_THEN apply_tac)) THEN (done_tac));
];;
(* Lemma mapP *)
let mapP = Sections.section_proof ["s";"y"]
`(y <- map f s) <=> (?x. x <- s /\ y = f x)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("andFb", [andFb]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("NOT_EXISTS_THM", [NOT_EXISTS_THM]))(thm_tac (new_rewrite [] [])))) THEN (move ["x"])) THEN (done_tac));
((repeat_tactic 1 9 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`y = f x`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["Hxy"])));
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (split_tac) [(case THEN ((move ["x'"]) THEN (case THEN ((move ["Hx'"]) THEN (move ["eq"]))))); (case THEN ((move ["x'"]) THEN (case THEN ((move ["Hx'"]) THEN (move ["Dy"])))))]));
(((use_arg_then2 ("x'", [])) (term_tac exists_tac)) THEN (done_tac));
((THENL) (((use_arg_then2 ("Hx'", [])) (disch_tac [])) THEN (clear_assumption "Hx'") THEN case THEN (move ["Hx'"])) [BETA_TAC; (((use_arg_then2 ("x'", [])) (term_tac exists_tac)) THEN ((TRY done_tac)))]);
(((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("Hxy", [])) (disch_tac [])) THEN (clear_assumption "Hxy") THEN BETA_TAC) THEN ((((use_arg_then2 ("Dy", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hx'", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_uniq *)
let map_uniq = Sections.section_proof ["s"]
`uniq (map f s) ==> uniq s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN ALL_TAC THEN (case THEN (move ["not_sfx"]))));
(((DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("andbT", [andbT]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("not_sfx", [])) (disch_tac [])) THEN (clear_assumption "not_sfx") THEN ((use_arg_then2 ("contra", [contra])) (disch_tac [])) THEN (clear_assumption "contra") THEN (DISCH_THEN apply_tac) THEN (move ["sx"])) THEN (((use_arg_then2 ("mapP", [mapP]))(thm_tac (new_rewrite [] [])))) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma map_inj_in_uniq *)
let map_inj_in_uniq = Sections.section_proof ["s"]
`(!x y. x <- s ==> y <- s ==> (f x = f y ==> x = y)) ==>
uniq (map f s) = uniq s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (((((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) THEN (move ["injf"])));
(((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))));
(BETA_TAC THEN (move ["a"]) THEN (move ["b"]) THEN (case THEN ((case THEN ((move ["Ha"]) THEN (move ["Hb"]))) THEN (move ["fab"]))));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("injf", [])) (fun fst_arg -> (use_arg_then2 ("a", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (use_arg_then2 ("b", [])) (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 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Ha", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hb", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("fab", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((congr_tac (`_ /\ _`)) THEN ((TRY done_tac)));
(((((use_arg_then2 ("mapP", [mapP]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("NOT_EXISTS_THM", [NOT_EXISTS_THM]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("negb_and", [negb_and]))(thm_tac (new_rewrite [] []))))) THEN (split_tac));
((((fun arg_tac -> (conv_thm_tac DISCH_THEN) (fun fst_arg -> (use_arg_then2 ("x", [])) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (thm_tac MP_TAC)) THEN BETA_TAC THEN (simp_tac)) THEN (done_tac));
(BETA_TAC THEN (move ["Hx"]) THEN (move ["y"]));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`y <- s`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac) THEN (move ["Hy"]));
((((fun arg_tac -> arg_tac (Arg_theorem (TAUT `~A <=> (A ==> F)`)))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (move ["fxy"]));
((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("injf", [])) (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 ("y", [])) (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 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("Hy", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("fxy", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`x = y`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN ((TRY done_tac)) THEN (move ["xy"]));
((((use_arg_then2 ("Hx", [])) (disch_tac [])) THEN (clear_assumption "Hx") THEN ((use_arg_then2 ("Hy", [])) (disch_tac [])) THEN (clear_assumption "Hy") THEN BETA_TAC) THEN (((use_arg_then2 ("xy", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma map_subseq *)
let map_subseq = Sections.section_proof ["s1";"s2"]
`subseq s1 s2 ==> subseq (map f s1) (map f s2)`
[
((repeat_tactic 1 9 (((use_arg_then2 ("subseqP", [subseqP]))(thm_tac (new_rewrite [] []))))) THEN ALL_TAC THEN (case THEN (move ["m"])) THEN (case THEN ((move ["sz_m"]) THEN (move ["eq"]))));
(((use_arg_then2 ("m", [])) (term_tac exists_tac)) THEN ((((use_arg_then2 ("eq", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("map_mask", [map_mask]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section EqMap *)
let map_f = Sections.finalize_theorem map_f;;
let mapP = Sections.finalize_theorem mapP;;
let map_uniq = Sections.finalize_theorem map_uniq;;
let map_inj_in_uniq = Sections.finalize_theorem map_inj_in_uniq;;
let map_subseq = Sections.finalize_theorem map_subseq;;
Sections.end_section "EqMap";;
(* Section EqMap2 *)
Sections.begin_section "EqMap2";;
(Sections.add_section_var (mk_var ("n0", (`:num`))));;
(Sections.add_section_var (mk_var ("x1", (`:A`))));;
(Sections.add_section_var (mk_var ("x2", (`:B`))));;
(Sections.add_section_var (mk_var ("f", (`:A -> B`))));;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(Sections.add_section_hyp "Hf" (`!x y. f x = f y ==> x = y`));;
(* Lemma inj_eq *)
let inj_eq = Sections.section_proof ["x";"y"]
`(f x = f y <=> x = y)`
[
(((THENL) (split_tac) [(DISCH_THEN (fun snd_th -> (use_arg_then2 ("Hf", [])) (thm_tac (match_mp_then snd_th MP_TAC)))); (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) THEN (done_tac));
];;
(* Lemma mem_map *)
let mem_map = Sections.section_proof ["s";"x"]
`(f x <- map f s) = (x <- s)`
[
((((use_arg_then2 ("mapP", [mapP]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (split_tac) [((case THEN ((move ["y"]) THEN (case THEN ((move ["Hy"]) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("Hf", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))))))) THEN ((TRY done_tac))); (move ["Hx"])]) THEN ((use_arg_then2 ("x", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma index_map *)
let index_map = Sections.section_proof ["s";"x"]
`indexl (f x) (map f s) = indexl x s`
[
((repeat_tactic 1 9 (((use_arg_then2 ("index", [index]))(thm_tac (new_rewrite [] []))))) THEN ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("find", [find]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("pred1", [pred1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac)));
(((((use_arg_then2 ("inj_eq", [inj_eq]))(gsym_then (thm_tac (new_rewrite [] [(`y = x`)]))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("pred1", [pred1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_inj_uniq *)
let map_inj_uniq = Sections.section_proof ["s"]
`uniq (map f s) = uniq s`
[
((((use_arg_then2 ("map_inj_in_uniq", [map_inj_in_uniq])) (disch_tac [])) THEN (clear_assumption "map_inj_in_uniq") THEN (DISCH_THEN apply_tac) THEN (move ["x"]) THEN (move ["y"]) THEN (move ["_"]) THEN (move ["_"]) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("Hf", [])) (thm_tac (match_mp_then snd_th MP_TAC))))) THEN (done_tac));
];;
(* Finalization of the section EqMap2 *)
let inj_eq = Sections.finalize_theorem inj_eq;;
let mem_map = Sections.finalize_theorem mem_map;;
let index_map = Sections.finalize_theorem index_map;;
let map_inj_uniq = Sections.finalize_theorem map_inj_uniq;;
Sections.end_section "EqMap2";;
(* Section MapComp *)
Sections.begin_section "MapComp";;
(* Lemma map_id *)
let map_id = Sections.section_proof ["s"]
`map I (s:(A)list) = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("I_THM", [I_THM]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma eq_map *)
let eq_map = Sections.section_proof ["f1";"f2"]
`(!x. (f1:A->B) x = f2 x) ==> map f1 = map f2`
[
(((((use_arg_then2 ("eq_ext", [eq_ext]))(thm_tac (new_rewrite [] [])))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma map_comp *)
let map_comp = Sections.section_proof ["f1";"f2";"s"]
`map (f1 o f2) s = map (f1:B->C) (map (f2:A->B) s)`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (repeat_tactic 1 9 (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("o_THM", [o_THM]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma mapK *)
let mapK = Sections.section_proof ["f1";"f2"]
`(!x. (f2:B->A) ((f1:A->B) x) = x) ==> (!s. map f2 (map f1 s) = s)`
[
((BETA_TAC THEN (move ["eq_f12"])) THEN ((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (repeat_tactic 1 9 (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Finalization of the section MapComp *)
let map_id = Sections.finalize_theorem map_id;;
let eq_map = Sections.finalize_theorem eq_map;;
let map_comp = Sections.finalize_theorem map_comp;;
let mapK = Sections.finalize_theorem mapK;;
Sections.end_section "MapComp";;
(* Lemma eq_in_map *)
let eq_in_map = Sections.section_proof ["f1";"f2";"s"]
`(!x. x <- s ==> (f1:A->B) x = f2 x) ==> map f1 s = map f2 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]) THEN (move ["eqf12"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("eqf12", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (move ["y"]) THEN (move ["sy"]));
(((((use_arg_then2 ("eqf12", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma map_id_in *)
let map_id_in = Sections.section_proof ["f";"s"]
`(!x. x <- s ==> f x = (x:A)) ==> map f s = s`
[
((DISCH_THEN (fun snd_th -> (use_arg_then2 ("eq_in_map", [eq_in_map])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))));
(((use_arg_then2 ("map_id", [map_id]))(gsym_then (thm_tac (new_rewrite [2] [(`s`)])))));
(((((fun arg_tac -> (fun arg_tac -> (use_arg_then2 ("eq_map", [eq_map])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`(\x. x)`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`I`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(thm_tac (new_rewrite [] [])))) THEN ((simp_tac THEN TRY done_tac)) THEN (((use_arg_then2 ("I_THM", [I_THM]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_iota *)
let size_iota = Sections.section_proof ["m";"n"]
`sizel (iota m n) = n`
[
(((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]) THEN (move ["m"]))]) THEN ((((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma iota_add *)
let iota_add = Sections.section_proof ["m";"n1";"n2"]
`iota m (n1 + n2) = iota m n1 ++ iota (m + n1) n2`
[
(((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN ((use_arg_then2 ("n1", [])) (disch_tac [])) THEN (clear_assumption "n1") THEN elim) [ALL_TAC; ((move ["n1"]) THEN (move ["IHn1"]))]) THEN ((((use_arg_then2 ("addn0", [addn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat0s", [cat0s]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("addSnnS", [addSnnS]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("addSn", [addSn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("IHn1", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("addSn", [addSn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat_cons", [cat_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma iota_addl *)
let iota_addl = Sections.section_proof ["m1";"m2";"n"]
`iota (m1 + m2) n = map ((+) m1) (iota m2 n)`
[
(((THENL) (((use_arg_then2 ("m2", [])) (disch_tac [])) THEN (clear_assumption "m2") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]) THEN (move ["m2"]))]) THEN ((((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("addnS", [addnS]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_iota *)
let nth_iota = Sections.section_proof ["m";"n";"i"]
`i < n ==> nth 0 (iota m n) i = m + i`
[
(((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("subnKC", [subnKC])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((((use_arg_then2 ("addSnnS", [addSnnS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("iota_add", [iota_add]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("nth_cat", [nth_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("subnn", [subnn]))(thm_tac (new_rewrite [] []))))));
(((((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma mem_iota *)
let mem_iota = Sections.section_proof ["m";"n";"i"]
`(i <- iota m n) <=> (m <= i) /\ (i < m + n)`
[
((((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN (move ["m"])) THEN ((((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("addn0", [addn0]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andbN", [andbN]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
((((use_arg_then2 ("addSnnS", [addSnnS]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("leq_eqVlt", [leq_eqVlt]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`i = m`)])))));
(((fun arg_tac -> (use_arg_then2 ("EXCLUDED_MIDDLE", [EXCLUDED_MIDDLE])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`m = i`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg))) (disch_tac [])) THEN case THEN (simp_tac));
(((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addSn", [addSn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_addr", [leq_addr]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
(((((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma iota_uniq *)
let iota_uniq = Sections.section_proof ["m";"n"]
`uniq (iota m n)`
[
(((THENL) (((use_arg_then2 ("m", [])) (disch_tac [])) THEN (clear_assumption "m") THEN ((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]) THEN (move ["m"]))]) THEN ((((use_arg_then2 ("iota", [iota]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("uniq", [uniq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("mem_iota", [mem_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("andFb", [andFb]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Section MakeSeq *)
Sections.begin_section "MakeSeq";;
(Sections.add_section_var (mk_var ("x0", (`:A`))));;
(* Lemma size_mkseq *)
let size_mkseq = Sections.section_proof ["f";"n"]
`sizel (mkseq f n) = n`
[
(((((use_arg_then2 ("mkseq", [mkseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma eq_mkseq *)
let eq_mkseq = Sections.section_proof ["f";"g"]
`(!x. f x = g x) ==> mkseq f = mkseq g`
[
((((((use_arg_then2 ("eq_ext", [eq_ext]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("mkseq", [mkseq]))(thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("eq_map", [eq_map])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_mkseq *)
let nth_mkseq = Sections.section_proof ["f";"n";"i"]
`i < n ==> nth x0 (mkseq f n) i = f i`
[
((BETA_TAC THEN (move ["Hi"])) THEN (((use_arg_then2 ("mkseq", [mkseq]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("nth_map", [nth_map]))(thm_tac (new_rewrite [] [])))) THEN ((fun arg_tac -> arg_tac (Arg_term (`0`))) (term_tac exists_tac)) THEN (((((use_arg_then2 ("size_iota", [size_iota]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hi", []))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["_"])));
(((((use_arg_then2 ("nth_iota", [nth_iota]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("add0n", [add0n]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma mkseq_nth *)
let mkseq_nth = Sections.section_proof ["s"]
`mkseq (nth x0 s) (sizel s) = 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))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (((((use_arg_then2 ("size_mkseq", [size_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac)) THEN (move ["i"]) THEN (move ["Hi"])) THEN (((use_arg_then2 ("nth_mkseq", [nth_mkseq]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Finalization of the section MakeSeq *)
let size_mkseq = Sections.finalize_theorem size_mkseq;;
let eq_mkseq = Sections.finalize_theorem eq_mkseq;;
let nth_mkseq = Sections.finalize_theorem nth_mkseq;;
let mkseq_nth = Sections.finalize_theorem mkseq_nth;;
Sections.end_section "MakeSeq";;
(* Lemma mkseq_uniq *)
let mkseq_uniq = Sections.section_proof ["f";"n"]
`(!x y. f x = f y ==> x = y) ==> uniq (mkseq f n)`
[
((DISCH_THEN (fun snd_th -> (use_arg_then2 ("map_inj_uniq", [map_inj_uniq])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN BETA_TAC THEN (move ["Hs"]));
(((((use_arg_then2 ("mkseq", [mkseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("Hs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("iota_uniq", [iota_uniq]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Section FoldRight *)
Sections.begin_section "FoldRight";;
(Sections.add_section_var (mk_var ("f", (`:A -> B -> B`))));;
(Sections.add_section_var (mk_var ("z0", (`:B`))));;
(* Finalization of the section FoldRight *)
Sections.end_section "FoldRight";;
(* Section FoldRightComp *)
Sections.begin_section "FoldRightComp";;
(Sections.add_section_var (mk_var ("h", (`:A->B`))));;
(Sections.add_section_var (mk_var ("f", (`:B->R->R`))));;
(Sections.add_section_var (mk_var ("z0", (`:R`))));;
(* Lemma foldr_cat *)
let foldr_cat = Sections.section_proof ["s1";"s2"]
`foldr f z0 (s1 ++ s2) = foldr f (foldr f z0 s2) s1`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma foldr_map *)
let foldr_map = Sections.section_proof ["s"]
`foldr f z0 (map h s) = foldr (\x z. f (h x) z) z0 s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Finalization of the section FoldRightComp *)
let foldr_cat = Sections.finalize_theorem foldr_cat;;
let foldr_map = Sections.finalize_theorem foldr_map;;
Sections.end_section "FoldRightComp";;
(* Lemma sumn0 *)
let sumn0 = Sections.section_proof []
`sumn [] = 0`
[
(((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma sumn_nseq *)
let sumn_nseq = Sections.section_proof ["x";"n"]
`sumn (nseq n x) = x * n`
[
((((use_arg_then2 ("mulnC", [mulnC]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (((use_arg_then2 ("n", [])) (disch_tac [])) THEN (clear_assumption "n") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["IHn"]))]) THEN ((((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mul0n", [mul0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("sumn", [sumn]))(gsym_then (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 ("IHn", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mulSn", [mulSn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma sumn_cat *)
let sumn_cat = Sections.section_proof ["s1";"s2"]
`sumn (s1 ++ s2) = sumn s1 + sumn s2`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn0", [sumn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("add0n", [add0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn", [sumn]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("IHs", []))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("addnA", [addnA]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma natnseq0P *)
let natnseq0P = Sections.section_proof ["s"]
`sumn s = 0 <=> s = nseq (sizel s) 0`
[
((THENL_LAST) ((THENL) (split_tac) [ALL_TAC; (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))]) (((((use_arg_then2 ("sumn_nseq", [sumn_nseq]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mul0n", [mul0n]))(thm_tac (new_rewrite [] []))))) THEN (done_tac)));
((THENL_FIRST) ((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) (((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac)));
((((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn", [sumn]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("addn_eq0", [addn_eq0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nseq", [nseq]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("iter", [iter]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ncons", [ncons]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("nseq", [nseq]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN ALL_TAC THEN (case THEN ((((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(gsym_then (thm_tac (new_rewrite [] [])))))))) THEN (done_tac));
];;
(* Section FoldLeft *)
Sections.begin_section "FoldLeft";;
(Sections.add_section_var (mk_var ("f", (`:R->A->R`))));;
(* Lemma foldl_rev *)
let foldl_rev = Sections.section_proof ["z";"s"]
`foldl f z (rev s) = foldr (\x z0. f z0 x) z s`
[
((((use_arg_then2 ("z", [])) (disch_tac [])) THEN (clear_assumption "z") THEN ((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((fun arg_tac -> arg_tac (Arg_theorem (REWRITE_RULE[IMP_IMP] last_ind))) (disch_tac [])) THEN (DISCH_THEN apply_tac)) THEN (((THENL) (split_tac) [ALL_TAC; ((move ["s"]) THEN (move ["x"]) THEN (move ["IHs"]))]) THEN (move ["z"])));
(((((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldl", [foldl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("rev_rcons", [rev_rcons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("foldr_cat", [foldr_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(gsym_then (thm_tac (new_rewrite [] []))))));
(((repeat_tactic 1 9 (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("foldl", [foldl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma foldl_cat *)
let foldl_cat = Sections.section_proof ["z";"s1";"s2"]
`foldl f z (s1 ++ s2) = foldl f (foldl f z s1) s2`
[
(((((fun arg_tac -> (use_arg_then2 ("revK", [revK])) (fun fst_arg -> (fun arg_tac -> arg_tac (Arg_term (`s1 ++ s2`))) (fun snd_arg -> combine_args_then arg_tac fst_arg snd_arg)))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("foldl_rev", [foldl_rev]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("rev_cat", [rev_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("foldr_cat", [foldr_cat]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("foldl_rev", [foldl_rev]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("revK", [revK]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Finalization of the section FoldLeft *)
let foldl_rev = Sections.finalize_theorem foldl_rev;;
let foldl_cat = Sections.finalize_theorem foldl_cat;;
Sections.end_section "FoldLeft";;
(* Section Scan *)
Sections.begin_section "Scan";;
(Sections.add_section_var (mk_var ("x1", (`:A`))));;
(Sections.add_section_var (mk_var ("x2", (`:B`))));;
(Sections.add_section_var (mk_var ("f", (`:A -> A -> B`))));;
(Sections.add_section_var (mk_var ("g", (`:A -> B -> A`))));;
(* Lemma size_pairmap *)
let size_pairmap = Sections.section_proof ["x";"s"]
`sizel (pairmap f x s) = sizel 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma pairmap_cat *)
let pairmap_cat = Sections.section_proof ["x";"s1";"s2"]
`pairmap f x (s1 ++ s2) = pairmap f x s1 ++ pairmap f (last x s1) s2`
[
((((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["IHs1"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("last", [last]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("IHs1", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma nth_pairmap *)
let nth_pairmap = Sections.section_proof ["s";"n"]
`n < sizel s ==>
!x. nth x2 (pairmap f x s) n = f (nth x1 (x :: s) n) (nth x1 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (move ["Hn"]) THEN (move ["x"])) THEN (done_tac));
];;
let scanl = define `scanl g x (y :: s) = g x y :: scanl g (g x y) s /\ scanl g x [] = []`;;
(* Lemma size_scanl *)
let size_scanl = Sections.section_proof ["x";"s"]
`sizel (scanl g x s) = sizel 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("scanl", [scanl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
];;
(* Lemma scanl_cat *)
let scanl_cat = Sections.section_proof ["x";"s1";"s2"]
`scanl g x (s1 ++ s2) = scanl g x s1 ++ scanl g (foldl g x s1) s2`
[
((((THENL) (((use_arg_then2 ("x", [])) (disch_tac [])) THEN (clear_assumption "x") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["y"]) THEN (move ["s1"]) THEN (move ["IHs1"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("scanl", [scanl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldl", [foldl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma nth_scanl *)
let nth_scanl = Sections.section_proof ["s";"n"]
`n < sizel s ==>
!x. nth x1 (scanl g x s) n = foldl g x (take (SUC n) 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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["n"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("scanl", [scanl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("take", [take]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("foldl", [foldl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltSS", [ltSS]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (move ["Hn"])) THEN (done_tac));
];;
(* Lemma scanlK *)
let scanlK = Sections.section_proof []
`(!x y. f x (g x y) = y) ==> (!x s. pairmap f x (scanl g x s) = s)`
[
(BETA_TAC THEN (move ["Hfg"]) THEN (move ["x"]) THEN (move ["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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("scanl", [scanl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma pairmapK *)
let pairmapK = Sections.section_proof []
`(!x y. g x (f x y) = y) ==> (!x s. scanl g x (pairmap f x s) = s)`
[
(BETA_TAC THEN (move ["Hgf"]) THEN (move ["x"]) THEN (move ["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 ["y"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN (move ["x"])) THEN ((((use_arg_then2 ("pairmap", [pairmap]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("scanl", [scanl]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Finalization of the section Scan *)
let size_pairmap = Sections.finalize_theorem size_pairmap;;
let pairmap_cat = Sections.finalize_theorem pairmap_cat;;
let nth_pairmap = Sections.finalize_theorem nth_pairmap;;
let size_scanl = Sections.finalize_theorem size_scanl;;
let scanl_cat = Sections.finalize_theorem scanl_cat;;
let nth_scanl = Sections.finalize_theorem nth_scanl;;
let scanlK = Sections.finalize_theorem scanlK;;
let pairmapK = Sections.finalize_theorem pairmapK;;
Sections.end_section "Scan";;
(* Section Zip *)
Sections.begin_section "Zip";;
let zip = define `zip (x :: s) (y :: t) = (x, y) :: zip s t /\
zip [] t = [] /\ zip s [] = []`;;
(* Lemma zip_unzip *)
let zip_unzip = Sections.section_proof ["s"]
`zip (unzip1 s) (unzip2 s) = s`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("unzip1", [unzip1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("unzip2", [unzip2]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("PAIR", [PAIR]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("unzip1", [unzip1]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("unzip2", [unzip2]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma unzip1_zip *)
let unzip1_zip = Sections.section_proof ["s";"t"]
`sizel s <= sizel t ==> unzip1 (zip s t) = s`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("unzip1", [unzip1]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("unzip1", [unzip1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma unzip2_zip *)
let unzip2_zip = Sections.section_proof ["s";"t"]
`sizel t <= sizel s ==> unzip2 (zip s t) = t`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("unzip2", [unzip2]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (simp_tac) THEN (((use_arg_then2 ("unzip2", [unzip2]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size1_zip *)
let size1_zip = Sections.section_proof ["s";"t"]
`sizel s <= sizel t ==> sizel (zip s t) = sizel s`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size2_zip *)
let size2_zip = Sections.section_proof ["s";"t"]
`sizel t <= sizel s ==> sizel (zip s t) = sizel t`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
((((((use_arg_then2 ("ltE", [ltE]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leqSS", [leqSS]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma size_zip *)
let size_zip = Sections.section_proof ["s";"t"]
`sizel (zip s t) = minn (sizel s) (sizel t)`
[
(((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["t2"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("minn", [minn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltnn", [ltnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (simp_tac) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("gtS0", [gtS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltS0", [ltS0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("minn", [minn]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("add1n", [add1n]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("addn_minr", [addn_minr]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("add1n", [add1n]))(thm_tac (new_rewrite [] [])))))) THEN (done_tac));
];;
(* Lemma zip_cat *)
let zip_cat = Sections.section_proof ["s1";"s2";"t1";"t2"]
`sizel s1 = sizel t1 ==> zip (s1 ++ s2) (t1 ++ t2) = zip s1 t1 ++ zip s2 t2`
[
(((THENL) (((use_arg_then2 ("t1", [])) (disch_tac [])) THEN (clear_assumption "t1") THEN ((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((repeat_tactic 0 10 (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`0 = _`)]))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHs", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_zip *)
let nth_zip = Sections.section_proof ["x";"y";"s";"t";"i"]
`sizel s = sizel t ==> nth (x, y) (zip s t) i = (nth x s i, nth y t i)`
[
(((THENL) (((use_arg_then2 ("t", [])) (disch_tac [])) THEN (clear_assumption "t") THEN ((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 ["i"]) THEN (move ["IHi"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y1"]) THEN (move ["s1"]) THEN (move ["_"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y2"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))) 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 [] []))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eq_sym", [eq_sym]))(thm_tac (new_rewrite [] [(`0 = _`)]))))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("eqS0", [eqS0]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] [])))) THEN (DISCH_THEN (fun snd_th -> (use_arg_then2 ("IHi", [])) (thm_tac (match_mp_then snd_th MP_TAC)))) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma nth_zip_cond *)
let nth_zip_cond = Sections.section_proof ["p";"s";"t";"i"]
`nth p (zip s t) i
= (if i < sizel (zip s t) then (nth (FST p) s i, nth (SND p) t i) else p)`
[
((((use_arg_then2 ("size_zip", [size_zip]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("ltnNge", [ltnNge]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_minl", [leq_minl]))(thm_tac (new_rewrite [] [])))));
(((THENL) (((use_arg_then2 ("i", [])) (disch_tac [])) THEN (clear_assumption "i") THEN ((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 ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["y"]) THEN (move ["t"]) THEN (move ["_"]))]) THEN ((THENL) elim [ALL_TAC; ((move ["i"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("leqnn", [leqnn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("nth", [nth]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("leq0n", [leq0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("IHs", []))(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 (done_tac));
];;
(* Lemma zip_rcons *)
let zip_rcons = Sections.section_proof ["s1";"s2";"z1";"z2"]
`sizel s1 = sizel s2 ==>
zip (rcons s1 z1) (rcons s2 z2) = rcons (zip s1 s2) (z1, z2)`
[
((BETA_TAC THEN (move ["eq_sz"])) THEN ((repeat_tactic 1 9 (((use_arg_then2 ("cats1", [cats1]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("zip_cat", [zip_cat]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (repeat_tactic 1 9 (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma rev_zip *)
let rev_zip = Sections.section_proof ["s1";"s2"]
`sizel s1 = sizel s2 ==> rev (zip s1 s2) = zip (rev s1) (rev 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 ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((THENL) case [ALL_TAC; ((move ["y"]) THEN (move ["s2"]))])) THEN (TRY ((((((use_arg_then2 ("rev", [rev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("catrev", [catrev]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac)))));
(((repeat_tactic 1 9 (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("eqSS", [eqSS]))(thm_tac (new_rewrite [] []))))) THEN (move ["eq_sz"]));
(((repeat_tactic 1 9 (((use_arg_then2 ("rev_cons", [rev_cons]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("zip_rcons", [zip_rcons]))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("size_rev", [size_rev]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac))) THEN ((((use_arg_then2 ("zip", [zip]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("rev_cons", [rev_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN ((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac))) THEN (done_tac));
];;
(* Finalization of the section Zip *)
let zip_unzip = Sections.finalize_theorem zip_unzip;;
let unzip1_zip = Sections.finalize_theorem unzip1_zip;;
let unzip2_zip = Sections.finalize_theorem unzip2_zip;;
let size1_zip = Sections.finalize_theorem size1_zip;;
let size2_zip = Sections.finalize_theorem size2_zip;;
let size_zip = Sections.finalize_theorem size_zip;;
let zip_cat = Sections.finalize_theorem zip_cat;;
let nth_zip = Sections.finalize_theorem nth_zip;;
let nth_zip_cond = Sections.finalize_theorem nth_zip_cond;;
let zip_rcons = Sections.finalize_theorem zip_rcons;;
let rev_zip = Sections.finalize_theorem rev_zip;;
Sections.end_section "Zip";;
(* Section Flatten *)
Sections.begin_section "Flatten";;
(Sections.add_section_type (mk_var ("s", (`:(A)list`))));;
(Sections.add_section_type (mk_var ("ss", (`:((A)list)list`))));;
let reshape = define `reshape (n :: sh) s = take n s :: reshape sh (dropl n s) /\
reshape [] s = []`;;
(* Lemma flatten0 *)
let flatten0 = Sections.section_proof []
`flatten [] = []`
[
(((((use_arg_then2 ("flatten", [flatten]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma flatten_cons *)
let flatten_cons = Sections.section_proof ["s";"ss"]
`flatten (s :: ss) = s ++ flatten ss`
[
(((((use_arg_then2 ("flatten", [flatten]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma size_flatten *)
let size_flatten = Sections.section_proof ["ss"]
`sizel (flatten ss) = sumn (shape ss)`
[
(((THENL) (((use_arg_then2 ("ss", [])) (disch_tac [])) THEN (clear_assumption "ss") THEN elim) [ALL_TAC; ((move ["s"]) THEN (move ["ss"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("flatten", [flatten]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("shape", [shape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn0", [sumn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("flatten", [flatten]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("shape", [shape]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN ((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma flatten_cat *)
let flatten_cat = Sections.section_proof ["ss1";"ss2"]
`flatten (ss1 ++ ss2) = flatten ss1 ++ flatten ss2`
[
(((THENL) (((use_arg_then2 ("ss1", [])) (disch_tac [])) THEN (clear_assumption "ss1") THEN elim) [ALL_TAC; ((move ["s"]) THEN (move ["ss1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("flatten0", [flatten0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("flatten_cons", [flatten_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma flattenK *)
let flattenK = Sections.section_proof ["ss"]
`reshape (shape ss) (flatten ss) = ss`
[
(((THENL) (((use_arg_then2 ("ss", [])) (disch_tac [])) THEN (clear_assumption "ss") THEN elim) [ALL_TAC; ((move ["s"]) THEN (move ["ss"]) THEN (move ["IHss"]))]) THEN ((((use_arg_then2 ("flatten", [flatten]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("shape", [shape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("reshape", [reshape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("take_size_cat", [take_size_cat]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("drop_size_cat", [drop_size_cat]))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("flatten", [flatten]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("shape", [shape]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHss", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma reshapeKr *)
let reshapeKr = Sections.section_proof ["sh";"s"]
`sizel s <= sumn sh ==> flatten (reshape sh s) = s`
[
((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("sh", [])) (disch_tac [])) THEN (clear_assumption "sh") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["sh"]) THEN (move ["IHsh"]) THEN (move ["s"]) THEN (move ["sz_s"]))]);
(((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("reshape", [reshape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("flatten0", [flatten0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("sumn0", [sumn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("ltE", [ltE]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (((use_arg_then2 ("ltn0", [ltn0]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("reshape", [reshape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("flatten", [flatten]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("flatten", [flatten]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))));
(((((use_arg_then2 ("IHsh", []))(thm_tac (new_rewrite [] [])))) THEN (repeat_tactic 0 10 (((use_arg_then2 ("cat_take_drop", [cat_take_drop]))(thm_tac (new_rewrite [] []))))) THEN ((TRY done_tac)) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_sub_add", [leq_sub_add]))(thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("sz_s", [])) (disch_tac [])) THEN (clear_assumption "sz_s") THEN BETA_TAC));
(((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
];;
(* Lemma reshapeKl *)
let reshapeKl = Sections.section_proof ["sh";"s"]
`sumn sh <= sizel s ==> shape (reshape sh s) = sh`
[
((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN ((use_arg_then2 ("sh", [])) (disch_tac [])) THEN (clear_assumption "sh") THEN elim) [ALL_TAC; ((move ["n"]) THEN (move ["sh"]) THEN (move ["IHsh"]) THEN (move ["s"]) THEN (move ["sz_s"]))]);
(((THENL) elim [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["_"]))]) THEN ((((use_arg_then2 ("reshape", [reshape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("shape", [shape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg])))) THEN (done_tac));
((((use_arg_then2 ("sz_s", [])) (disch_tac [])) THEN (clear_assumption "sz_s") THEN BETA_TAC) THEN (((((use_arg_then2 ("sumn", [sumn]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("sumn", [sumn]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (move ["sz_s"])));
(((((use_arg_then2 ("reshape", [reshape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("shape", [shape]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("map", [map]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("shape", [shape]))(gsym_then (fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))))) THEN (((use_arg_then2 ("size_takel", [size_takel]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("sz_s", [])) (disch_tac [])) THEN (clear_assumption "sz_s") THEN ((use_arg_then2 ("leq_trans", [leq_trans])) (disch_tac [])) THEN (clear_assumption "leq_trans") THEN (DISCH_THEN apply_tac)) THEN (((use_arg_then2 ("leq_addr", [leq_addr]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
(((((use_arg_then2 ("IHsh", []))(thm_tac (new_rewrite [] [])))) THEN ((TRY done_tac)) THEN (((fun arg_tac -> (use_arg_then2 ("leq_add2l", [leq_add2l])) (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 [] []))))) THEN (((use_arg_then2 ("size_drop", [size_drop]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("add_sub_maxn", [add_sub_maxn]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("leq_maxr", [leq_maxr]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("sz_s", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("orbT", [orbT]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section Flatten *)
let flatten0 = Sections.finalize_theorem flatten0;;
let flatten_cons = Sections.finalize_theorem flatten_cons;;
let size_flatten = Sections.finalize_theorem size_flatten;;
let flatten_cat = Sections.finalize_theorem flatten_cat;;
let flattenK = Sections.finalize_theorem flattenK;;
let reshapeKr = Sections.finalize_theorem reshapeKr;;
let reshapeKl = Sections.finalize_theorem reshapeKl;;
Sections.end_section "Flatten";;
(* Section AllPairs *)
Sections.begin_section "AllPairs";;
(Sections.add_section_var (mk_var ("f", (`:S->T->R`))));;
(Sections.add_section_type (mk_var ("s", (`:(S)list`))));;
(Sections.add_section_type (mk_var ("t", (`:(T)list`))));;
(* Lemma size_allpairs *)
let size_allpairs = Sections.section_proof ["s";"t"]
`sizel (allpairs f s t) = sizel s * sizel t`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("allpairs", [allpairs]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("size_nil", [size_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("mul0n", [mul0n]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("size_cat", [size_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("allpairs", [allpairs]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_map", [size_map]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("size_cons", [size_cons]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mulSn", [mulSn]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Lemma allpairs_cat *)
let allpairs_cat = Sections.section_proof ["s1";"s2";"t"]
`allpairs f (s1 ++ s2) t = allpairs f s1 t ++ allpairs f s2 t`
[
(((THENL) (((use_arg_then2 ("s1", [])) (disch_tac [])) THEN (clear_assumption "s1") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s1"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("allpairs", [allpairs]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("cat", [cat]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((repeat_tactic 1 9 (((use_arg_then2 ("allpairs", [allpairs]))(gsym_then (thm_tac (new_rewrite [] [])))))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("catA", [catA]))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section AllPairs *)
let size_allpairs = Sections.finalize_theorem size_allpairs;;
let allpairs_cat = Sections.finalize_theorem allpairs_cat;;
Sections.end_section "AllPairs";;
(* Section EqAllPairs *)
Sections.begin_section "EqAllPairs";;
(Sections.add_section_var (mk_var ("f", (`:S->T->R`))));;
(Sections.add_section_type (mk_var ("s", (`:(S)list`))));;
(Sections.add_section_type (mk_var ("t", (`:(T)list`))));;
(* Lemma allpairsP *)
let allpairsP = Sections.section_proof ["s";"t";"z"]
`(z <- allpairs f s t) <=> (?p. FST p <- s /\ SND p <- t /\ z = f (FST p) (SND p))`
[
(((THENL) (((use_arg_then2 ("s", [])) (disch_tac [])) THEN (clear_assumption "s") THEN elim) [ALL_TAC; ((move ["x"]) THEN (move ["s"]) THEN (move ["IHs"]))]) THEN ((((use_arg_then2 ("allpairs", [allpairs]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("foldr", [foldr]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN (((use_arg_then2 ("in_nil", [in_nil]))(fun arg -> ONCE_REWRITE_TAC[get_arg_thm arg]))) THEN ((TRY done_tac))));
(((((use_arg_then2 ("allpairs", [allpairs]))(gsym_then (thm_tac (new_rewrite [] []))))) THEN (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("mapP", [mapP]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("IHs", []))(thm_tac (new_rewrite [] []))))) THEN (split_tac));
((THENL_FIRST) ((THENL) case [((case THEN (move ["y"])) THEN (case THEN ((move ["Hy"]) THEN (move ["eq"])))); ((case THEN (move ["p"])) THEN (case THEN ((move ["p1"]) THEN (case THEN ((move ["p2"]) THEN (move ["eq"]))))))]) ((((fun arg_tac -> arg_tac (Arg_term (`(x, y)`))) (term_tac exists_tac)) THEN (simp_tac)) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (done_tac)));
(((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (done_tac));
((((use_arg_then2 ("in_cons", [in_cons]))(thm_tac (new_rewrite [] [])))) THEN (BETA_TAC THEN (case THEN (move ["p"])) THEN (case THEN (case THEN (move ["p_s"]))) THEN (case THEN ((move ["p_t"]) THEN (move ["eq"])))));
((DISJ1_TAC) THEN ((fun arg_tac -> arg_tac (Arg_term (`SND p`))) (term_tac exists_tac)) THEN (done_tac));
((DISJ2_TAC) THEN ((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma mem_allpairs *)
let mem_allpairs = Sections.section_proof ["s1";"t1";"s2";"t2"]
`(!x. x <- s1 <=> x <- s2) ==> (!y. y <- t1 <=> y <- t2)
==> (!p. p <- allpairs f s1 t1 <=> p <- allpairs f s2 t2)`
[
(BETA_TAC THEN (move ["eq_s"]) THEN (move ["eq_t"]) THEN (move ["z"]));
((repeat_tactic 1 9 (((use_arg_then2 ("allpairsP", [allpairsP]))(thm_tac (new_rewrite [] []))))) THEN ((split_tac) THEN ALL_TAC THEN (case THEN (move ["p"]))) THEN (((((use_arg_then2 ("eq_s", []))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("eq_t", []))(thm_tac (new_rewrite [] []))))) THEN (move ["fpz"])));
(((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (done_tac));
(((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (done_tac));
];;
(* Lemma allpairs_catr *)
let allpairs_catr = Sections.section_proof ["s";"t1";"t2"]
`!p. p <- allpairs f s (t1 ++ t2) <=> p <- allpairs f s t1 ++ allpairs f s t2`
[
((BETA_TAC THEN (move ["z"])) THEN (((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))));
((((use_arg_then2 ("allpairsP", [allpairsP]))(thm_tac (new_rewrite [] [])))) THEN ((THENL) (split_tac) [(case THEN ((move ["p"]) THEN (case THEN (move ["sP1"])))); ALL_TAC]));
(((THENL) ((((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN ((case THEN (move ["H"])) THEN (((conv_thm_tac DISCH_THEN)(thm_tac (new_rewrite [] []))))))) [(DISJ1_TAC); (DISJ2_TAC)]) THEN (((use_arg_then2 ("allpairsP", [allpairsP]))(thm_tac (new_rewrite [] [])))) THEN ((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN (done_tac));
(case THEN ((((use_arg_then2 ("allpairsP", [allpairsP]))(thm_tac (new_rewrite [] [])))) THEN ALL_TAC THEN (case THEN (move ["p"])) THEN (case THEN (move ["sp1"])) THEN (case THEN ((move ["sp2"]) THEN (move ["eq"])))) THEN ((use_arg_then2 ("p", [])) (term_tac exists_tac)) THEN ((((use_arg_then2 ("mem_cat", [mem_cat]))(thm_tac (new_rewrite [] [])))) THEN (((use_arg_then2 ("sp2", []))(thm_tac (new_rewrite [] []))))) THEN (done_tac));
];;
(* Finalization of the section EqAllPairs *)
let allpairsP = Sections.finalize_theorem allpairsP;;
let mem_allpairs = Sections.finalize_theorem mem_allpairs;;
let allpairs_catr = Sections.finalize_theorem allpairs_catr;;
Sections.end_section "EqAllPairs";;
(* Close the module *)
end;;